From 937c2869b2c1eb363ca9b54b6e4c0dcb2a477da1 Mon Sep 17 00:00:00 2001 From: Mo Chen Date: Wed, 13 Apr 2022 13:48:43 -0500 Subject: [PATCH 1/4] File change monitoring on s3_auth -Add a file change monitoring API -Use it to monitor config changes for s3_auth --- configure.ac | 8 +- doc/admin-guide/plugins/s3_auth.en.rst | 8 +- .../testing/blackbox-testing.en.rst | 1 + include/ts/apidefs.h.in | 12 + include/ts/ts.h | 17 ++ include/tscore/ink_config.h.in | 1 + iocore/Makefile.am | 2 +- iocore/fs/FileChange.cc | 227 ++++++++++++++++++ iocore/fs/FileChange.h | 84 +++++++ iocore/fs/Makefile.am | 34 +++ plugins/s3_auth/s3_auth.cc | 193 ++++++++++++++- src/traffic_layout/info.cc | 1 + src/traffic_server/InkAPI.cc | 21 ++ src/traffic_server/Makefile.inc | 1 + src/traffic_server/traffic_server.cc | 4 + tests/README.md | 1 + .../s3_auth/gold/s3_auth_basic.gold | 34 +++ .../s3_auth/gold/traffic_server.gold | 2 + .../pluginTest/s3_auth/rules/region_map.conf | 1 + .../pluginTest/s3_auth/rules/v4-modified.conf | 4 + .../pluginTest/s3_auth/rules/v4.conf | 4 + .../pluginTest/s3_auth/s3_auth_basic.test.py | 87 +++++++ 22 files changed, 739 insertions(+), 8 deletions(-) create mode 100644 iocore/fs/FileChange.cc create mode 100644 iocore/fs/FileChange.h create mode 100644 iocore/fs/Makefile.am create mode 100644 tests/gold_tests/pluginTest/s3_auth/gold/s3_auth_basic.gold create mode 100644 tests/gold_tests/pluginTest/s3_auth/gold/traffic_server.gold create mode 100644 tests/gold_tests/pluginTest/s3_auth/rules/region_map.conf create mode 100644 tests/gold_tests/pluginTest/s3_auth/rules/v4-modified.conf create mode 100644 tests/gold_tests/pluginTest/s3_auth/rules/v4.conf create mode 100644 tests/gold_tests/pluginTest/s3_auth/s3_auth_basic.test.py diff --git a/configure.ac b/configure.ac index 64192700df2..67d57c45ae4 100644 --- a/configure.ac +++ b/configure.ac @@ -1808,6 +1808,10 @@ AC_LANG_POP([C++]) # Right now, the healthcheck plugins requires inotify_init (and friends) AM_CONDITIONAL([BUILD_HEALTHCHECK_PLUGIN], [ test "$ac_cv_func_inotify_init" = "yes" ]) +use_inotify=0 +AS_IF([test "x$ac_cv_func_inotify_init" = "xyes"], [use_inotify=1]) +AC_SUBST(use_inotify) + # # Check for tcmalloc, jemalloc and mimalloc TS_CHECK_TCMALLOC @@ -2252,7 +2256,8 @@ iocore_include_dirs="\ -I\$(abs_top_srcdir)/iocore/hostdb \ -I\$(abs_top_srcdir)/iocore/cache \ -I\$(abs_top_srcdir)/iocore/utils \ --I\$(abs_top_srcdir)/iocore/dns" +-I\$(abs_top_srcdir)/iocore/dns \ +-I\$(abs_top_srcdir)/iocore/fs" AC_SUBST([AM_CPPFLAGS]) AC_SUBST([AM_CFLAGS]) @@ -2300,6 +2305,7 @@ AC_CONFIG_FILES([ iocore/cache/Makefile iocore/dns/Makefile iocore/eventsystem/Makefile + iocore/fs/Makefile iocore/hostdb/Makefile iocore/net/Makefile iocore/net/quic/Makefile diff --git a/doc/admin-guide/plugins/s3_auth.en.rst b/doc/admin-guide/plugins/s3_auth.en.rst index 87f1a92097c..23da86ed698 100644 --- a/doc/admin-guide/plugins/s3_auth.en.rst +++ b/doc/admin-guide/plugins/s3_auth.en.rst @@ -44,7 +44,7 @@ Alternatively, you can store the access key and secret in an external configurat # remap.config - ... @plugin=s3_auth.so @pparam=--config @pparam=s3_auth_v2.config + ... @plugin=s3_auth.so @pparam=--config @pparam=s3_auth_v2.config @pparam=--watch-config @pparam=--ttl=5 Where ``s3.config`` could look like:: @@ -94,6 +94,8 @@ The ``s3_auth_v4.config`` config file could look like this:: v4-include-headers= v4-exclude-headers= v4-region-map=region_map.config + watch-config + ttl=20 Where the ``region_map.config`` defines the entry-point hostname to region mapping i.e.:: @@ -123,6 +125,10 @@ If ``--v4-include-headers`` is not specified all headers except those specified If ``--v4-include-headers`` is specified only the headers specified will be signed except those specified in ``--v4-exclude-headers`` +If ``--watch-config`` is specified, the plugin will reload the config file set in ``--config`` when it changes + +If ``--ttl`` is specified, the plugin will cache configs for the specified number of seconds. During the ttl period, manual config reloads and ``--watch-config`` will not cause the config to be updated. The default is 60 seconds. Setting ttl to zero causes all reloads to read from the config file. This option is useful if the config file is fetched from a service, and you wish to limit the fetch rate. + AWS Authentication version 2 ============================ diff --git a/doc/developer-guide/testing/blackbox-testing.en.rst b/doc/developer-guide/testing/blackbox-testing.en.rst index 25af57aec31..5ca6f3f579a 100644 --- a/doc/developer-guide/testing/blackbox-testing.en.rst +++ b/doc/developer-guide/testing/blackbox-testing.en.rst @@ -262,6 +262,7 @@ Condition Testing - TS_HAS_128BIT_CAS - TS_HAS_TESTS - TS_HAS_WCCP + - TS_USE_INOTIFY Examples: diff --git a/include/ts/apidefs.h.in b/include/ts/apidefs.h.in index ac550a95fd6..efacb7435f1 100644 --- a/include/ts/apidefs.h.in +++ b/include/ts/apidefs.h.in @@ -554,6 +554,11 @@ typedef enum { TS_EVENT_SSL_CLIENT_HELLO = 60207, TS_EVENT_SSL_SECRET = 60208, + TS_EVENT_FILE_CREATED = 60300, + TS_EVENT_FILE_UPDATED = 60301, + TS_EVENT_FILE_DELETED = 60302, + TS_EVENT_FILE_IGNORED = 60303, + TS_EVENT_MGMT_UPDATE = 60300 } TSEvent; #define TS_EVENT_HTTP_READ_REQUEST_PRE_REMAP TS_EVENT_HTTP_PRE_REMAP /* backwards compat */ @@ -1454,6 +1459,13 @@ namespace ts } #endif +typedef int TSWatchDescriptor; +typedef enum { TS_WATCH_CREATE, TS_WATCH_DELETE, TS_WATCH_MODIFY } TSFileWatchKind; +typedef struct { + TSWatchDescriptor wd; + const char *name; +} TSFileWatchData; + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/include/ts/ts.h b/include/ts/ts.h index 4d35972e7e0..12cb1a8a3b2 100644 --- a/include/ts/ts.h +++ b/include/ts/ts.h @@ -2720,6 +2720,23 @@ tsapi void TSHostStatusSet(const char *hostname, const size_t hostname_len, TSHo tsapi bool TSHttpTxnCntlGet(TSHttpTxn txnp, TSHttpCntlType ctrl); tsapi TSReturnCode TSHttpTxnCntlSet(TSHttpTxn txnp, TSHttpCntlType ctrl, bool data); +/* + * Get notified for file system events + * + * Currently, this only works in Linux using inotify. + * + * TODO: Fix multiple plugins watching the same path. + * + * The edata (a.k.a. cookie) field of the continuation handler will contain information + * depending on the type of file event. edata is always a pointer to a TSFileWatchData. + * If the event is TS_EVENT_FILE_CREATED, name is a pointer to a null-terminated string + * containing the file name. Otherwise, name is a nullptr. wd is the watch descriptor + * for the event. + * + */ +tsapi TSWatchDescriptor TSFileEventRegister(const char *filename, TSFileWatchKind kind, TSCont contp); +tsapi void TSFileEventUnRegister(TSWatchDescriptor wd); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/include/tscore/ink_config.h.in b/include/tscore/ink_config.h.in index 5b297efe7bf..b6e635f4f31 100644 --- a/include/tscore/ink_config.h.in +++ b/include/tscore/ink_config.h.in @@ -83,6 +83,7 @@ #define TS_HAS_TLS_EARLY_DATA @has_tls_early_data@ #define TS_HAS_TLS_SESSION_TICKET @has_tls_session_ticket@ #define TS_HAS_VERIFY_CERT_STORE @has_verify_cert_store@ +#define TS_USE_INOTIFY @use_inotify@ #define TS_USE_HRW_GEOIP @use_hrw_geoip@ #define TS_USE_HRW_MAXMINDDB @use_hrw_maxminddb@ diff --git a/iocore/Makefile.am b/iocore/Makefile.am index 5aae15ea552..f870d193ba5 100644 --- a/iocore/Makefile.am +++ b/iocore/Makefile.am @@ -16,4 +16,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -SUBDIRS = eventsystem net aio dns hostdb utils cache +SUBDIRS = eventsystem net aio dns hostdb utils cache fs diff --git a/iocore/fs/FileChange.cc b/iocore/fs/FileChange.cc new file mode 100644 index 00000000000..864df401f39 --- /dev/null +++ b/iocore/fs/FileChange.cc @@ -0,0 +1,227 @@ +/** @file FileChange.cc + + Watch for file system changes. + + @section license License + + 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. + */ + +#include "FileChange.h" +#include "tscore/Diags.h" +#include "P_EventSystem.h" + +#include +#include +#include +#include + +// Globals +FileChangeManager fileChangeManager; +static constexpr auto TAG ATS_UNUSED = "FileChange"; + +// Wrap a continuation +class FileChangeCallback : public Continuation +{ +public: + explicit FileChangeCallback(Continuation *contp, TSEvent event) : Continuation(contp->mutex.get()), m_cont(contp), m_event(event) + { + SET_HANDLER(&FileChangeCallback::event_handler); + } + + int + event_handler(int, void *eventp) + { + Event *e = reinterpret_cast(eventp); + if (m_cont->mutex) { + MUTEX_TRY_LOCK(trylock, m_cont->mutex, this_ethread()); + if (!trylock.is_locked()) { + eventProcessor.schedule_in(this, HRTIME_MSECONDS(10), ET_TASK); + } else { + m_cont->handleEvent(m_event, e->cookie); + delete this; + } + } else { + m_cont->handleEvent(m_event, e->cookie); + delete this; + } + + return 0; + } + + std::string filename; // File name if the event is a file creation event. This is used in the cookie for a create event. + TSFileWatchData data; + +private: + Continuation *m_cont; + TSEvent m_event; +}; + +#if TS_USE_INOTIFY +static constexpr size_t INOTIFY_BUF_SIZE = 4096; + +static void +invoke(FileChangeCallback *cb) +{ + void *cookie = static_cast(&cb->data); + eventProcessor.schedule_imm(cb, ET_TASK, 1, cookie); +} + +void +FileChangeManager::process_file_event(struct inotify_event *event) +{ + std::shared_lock file_watches_read_lock(file_watches_mutex); + auto finfo_it = file_watches.find(event->wd); + if (finfo_it != file_watches.end()) { + TSEvent event_type = TS_EVENT_NONE; + const struct file_info &finfo = finfo_it->second; + Continuation *contp = finfo.contp; + + if (event->mask & (IN_DELETE_SELF | IN_MOVED_FROM)) { + Debug(TAG, "Delete file event (%d) on %s", event->mask, finfo.path.c_str()); + int rc2 = inotify_rm_watch(inotify_fd, event->wd); + if (rc2 == -1) { + Error("Failed to remove inotify watch on %s: %s (%d)", finfo.path.c_str(), strerror(errno), errno); + } + event_type = TS_EVENT_FILE_DELETED; + FileChangeCallback *cb = new FileChangeCallback(contp, event_type); + cb->data.wd = event->wd; + cb->data.name = nullptr; + invoke(cb); + } + + if (event->mask & (IN_CREATE | IN_MOVED_TO)) { + // Name may be padded with nul characters. Trim them. + auto len = strnlen(event->name, event->len); + std::string name{event->name, len}; + Debug(TAG, "Create file event (%d) on %s (wd = %d): %s", event->mask, finfo.path.c_str(), event->wd, name.c_str()); + event_type = TS_EVENT_FILE_CREATED; + + FileChangeCallback *cb = new FileChangeCallback(contp, event_type); + cb->filename = name; + cb->data.wd = event->wd; + cb->data.name = cb->filename.c_str(); + invoke(cb); + } + + if (event->mask & (IN_CLOSE_WRITE | IN_ATTRIB)) { + Debug(TAG, "Modify file event (%d) on %s (wd = %d)", event->mask, finfo.path.c_str(), event->wd); + event_type = TS_EVENT_FILE_UPDATED; + FileChangeCallback *cb = new FileChangeCallback(contp, event_type); + cb->data.wd = event->wd; + cb->data.name = nullptr; + invoke(cb); + } + + if (event->mask & (IN_IGNORED)) { + Debug(TAG, "Ignored file event (%d) on %s (wd = %d)", event->mask, finfo.path.c_str(), event->wd); + event_type = TS_EVENT_FILE_IGNORED; + FileChangeCallback *cb = new FileChangeCallback(contp, event_type); + cb->data.wd = event->wd; + cb->data.name = nullptr; + invoke(cb); + } + } +} +#endif + +void +FileChangeManager::init() +{ +#if TS_USE_INOTIFY + // TODO: auto configure based on whether inotify is available + inotify_fd = inotify_init1(IN_CLOEXEC); + if (inotify_fd == -1) { + Error("Failed to init inotify: %s (%d)", strerror(errno), errno); + return; + } + auto inotify_thread = [manager = this]() mutable { + for (;;) { + char inotify_buf[INOTIFY_BUF_SIZE]; + + // blocking read + ssize_t rc = read(manager->inotify_fd, inotify_buf, sizeof inotify_buf); + + if (rc == -1) { + Error("Failed to read inotify: %s (%d)", strerror(errno), errno); + if (errno == EINTR) { + continue; + } else { + break; + } + } + + ssize_t offset = 0; + while (offset < rc) { + struct inotify_event *event = reinterpret_cast(inotify_buf + offset); + + // Process file events + manager->process_file_event(event); + offset += sizeof(struct inotify_event) + event->len; + } + } + }; + poll_thread = std::thread(inotify_thread); + poll_thread.detach(); +#else + // Implement this +#endif +} + +watch_handle_t +FileChangeManager::add(const ts::file::path &path, TSFileWatchKind kind, Continuation *contp) +{ +#if TS_USE_INOTIFY + Debug(TAG, "Adding a watch on %s", path.c_str()); + watch_handle_t wd = 0; + + // Let the OS handle multiple watches on one file. + uint32_t mask = 0; + if (kind == TS_WATCH_CREATE) { + mask = IN_CREATE | IN_MOVED_TO | IN_ONLYDIR; + } else if (kind == TS_WATCH_DELETE) { + mask = IN_DELETE_SELF | IN_MOVED_FROM; + } else if (kind == TS_WATCH_MODIFY) { + mask = IN_CLOSE_WRITE | IN_ATTRIB; + } + wd = inotify_add_watch(inotify_fd, path.c_str(), mask); + if (wd == -1) { + Error("Failed to add file watch on %s: %s (%d)", path.c_str(), strerror(errno), errno); + return -1; + } else { + std::unique_lock file_watches_write_lock(file_watches_mutex); + file_watches[wd] = {path, contp}; + } + + Debug(TAG, "Watch handle = %d", wd); + return wd; +#else + Warning("File change notification is not supported on this OS."); + return 0; +#endif +} + +void +FileChangeManager::remove(watch_handle_t watch_handle) +{ +#if TS_USE_INOTIFY + Debug(TAG, "Deleting watch %d", watch_handle); + inotify_rm_watch(inotify_fd, watch_handle); + std::unique_lock file_watches_write_lock(file_watches_mutex); + file_watches.erase(watch_handle); +#endif +} diff --git a/iocore/fs/FileChange.h b/iocore/fs/FileChange.h new file mode 100644 index 00000000000..40437c221ec --- /dev/null +++ b/iocore/fs/FileChange.h @@ -0,0 +1,84 @@ +/** @file FileChange.h + + Watch for file system changes. + + @section license License + + 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. + */ + +#pragma once +#include "tscore/ink_config.h" + +#include +#include +#include +#include +#include +#include +#include "tscore/ts_file.h" +#include "P_EventSystem.h" + +#if TS_USE_INOTIFY +#include +#else +// implement this +#endif + +using watch_handle_t = int; + +// File watch info +struct file_info { + ts::file::path path; + Continuation *contp; +}; + +constexpr int MAX_WATCHES = 10000; + +class FileChangeManager +{ +public: + FileChangeManager() {} + + void init(); + + /** + Add a file watch + + @return a watch handle, or -1 on error + */ + watch_handle_t add(const ts::file::path &path, TSFileWatchKind kind, Continuation *contp); + + /** + Remove a file watch + */ + void remove(watch_handle_t watch_handle); + +private: + std::thread poll_thread; + +#if TS_USE_INOTIFY + void process_file_event(struct inotify_event *event); + std::shared_mutex file_watches_mutex; + std::unordered_map file_watches; + int inotify_fd; +#else + // implement this +#endif +}; + +extern FileChangeManager fileChangeManager; diff --git a/iocore/fs/Makefile.am b/iocore/fs/Makefile.am new file mode 100644 index 00000000000..a851273eadc --- /dev/null +++ b/iocore/fs/Makefile.am @@ -0,0 +1,34 @@ +# Makefile.am for the traffic/iocore/fs hierarchy +# +# 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. + +AM_CPPFLAGS += \ + $(iocore_include_dirs) \ + -I$(abs_top_srcdir)/include \ + -I$(abs_top_srcdir)/lib \ + $(TS_INCLUDES) + +noinst_LIBRARIES = libinkfs.a + +libinkfs_a_SOURCES = \ + FileChange.cc \ + FileChange.h + +include $(top_srcdir)/build/tidy.mk + +clang-tidy-local: $(DIST_SOURCES) + $(CXX_Clang_Tidy) diff --git a/plugins/s3_auth/s3_auth.cc b/plugins/s3_auth/s3_auth.cc index df5c090779c..50498822a60 100644 --- a/plugins/s3_auth/s3_auth.cc +++ b/plugins/s3_auth/s3_auth.cc @@ -42,11 +42,13 @@ #include #include #include +#include #include #include #include #include "tscore/ink_config.h" +#include "tscore/ts_file.h" #include "aws_auth_v4.h" @@ -161,21 +163,22 @@ class ConfigCache // never indicate config is fresh when it isn't. std::atomic config; std::atomic load_time; + std::atomic ttl = 60; _ConfigData() {} - _ConfigData(S3Config *config_, time_t load_time_) : config(config_), load_time(load_time_) {} + _ConfigData(S3Config *config_, time_t load_time_, int ttl_) : config(config_), load_time(load_time_), ttl(ttl_) {} _ConfigData(_ConfigData &&lhs) { update_status = lhs.update_status.load(); config = lhs.config.load(); load_time = lhs.load_time.load(); + ttl = lhs.ttl.load(); } }; std::unordered_map _cache; - static const int _ttl = 60; }; ConfigCache gConfCache; @@ -185,6 +188,8 @@ ConfigCache gConfCache; // int event_handler(TSCont, TSEvent, void *); // Forward declaration int config_reloader(TSCont, TSEvent, void *); +int config_dir_watch(TSCont, TSEvent, void *); +int config_watch(TSCont, TSEvent, void *); class S3Config { @@ -197,6 +202,12 @@ class S3Config _conf_rld = TSContCreate(config_reloader, TSMutexCreate()); TSContDataSet(_conf_rld, static_cast(this)); + + _dir_watch = TSContCreate(config_dir_watch, TSMutexCreate()); + TSContDataSet(_dir_watch, static_cast(this)); + + _conf_watch = TSContCreate(config_watch, TSMutexCreate()); + TSContDataSet(_conf_watch, static_cast(this)); } } @@ -302,6 +313,10 @@ class S3Config TSfree(_conf_fname); _conf_fname = TSstrdup(src->_conf_fname); } + + if (src->_watch_config) { + _watch_config = src->_watch_config; + } } // Getters @@ -383,6 +398,18 @@ class S3Config return _conf_fname; } + bool + watch_config() const + { + return _watch_config; + } + + int + ttl() const + { + return _ttl; + } + int incr_conf_reload_count() { @@ -463,6 +490,18 @@ class S3Config _conf_fname = TSstrdup(s); } + void + set_watch_config() + { + _watch_config = true; + } + + void + set_ttl(const char *s) + { + _ttl = strtol(s, nullptr, 10); + } + void reset_conf_reload_count() { @@ -489,7 +528,70 @@ class S3Config _conf_rld_act = TSContScheduleOnPool(_conf_rld, delay * 1000, TS_THREAD_POOL_NET); } + void + start_watch_config() + { + std::unique_lock lock(wd_mutex); + ts::file::path fname{makeConfigPath(_conf_fname)}; + if (!_config_file_wd) { + _config_file_wd = TSFileEventRegister(fname.c_str(), TS_WATCH_MODIFY, _conf_watch); + if (_config_file_wd == -1) { + _config_file_wd.reset(); + TSDebug(PLUGIN_NAME, "Waiting for config file to be created: %s", fname.c_str()); + } else { + TSDebug(PLUGIN_NAME, "Watching config file: %s (%d)", fname.c_str(), _config_file_wd.value()); + } + } + + if (!_config_dir_wd) { + auto parent_dir = fname.parent_path(); + _config_dir_wd = TSFileEventRegister(parent_dir.c_str(), TS_WATCH_CREATE, _dir_watch); + if (_config_dir_wd == -1) { + _config_dir_wd.reset(); + TSError("s3_auth: failed to watch config file directory: %s", parent_dir.c_str()); + } else { + TSDebug(PLUGIN_NAME, "Watching config file directory: %s (%d)", parent_dir.c_str(), _config_file_wd.value()); + } + } + } + + void + stop_watch_config() + { + std::unique_lock lock(wd_mutex); + if (_config_file_wd) { + TSFileEventUnRegister(_config_file_wd.value()); + _config_file_wd.reset(); + } + + if (_config_dir_wd) { + TSFileEventUnRegister(_config_dir_wd.value()); + _config_dir_wd.reset(); + } + } + + void + config_file_watch_ignored(TSWatchDescriptor wd) + { + std::unique_lock lock(wd_mutex); + if (_config_file_wd == wd) { + TSFileEventUnRegister(_config_file_wd.value()); + _config_file_wd.reset(); + } + } + + void + config_dir_watch_ignored(TSWatchDescriptor wd) + { + std::unique_lock lock(wd_mutex); + if (_config_dir_wd == wd) { + TSFileEventUnRegister(_config_dir_wd.value()); + _config_dir_wd.reset(); + } + } + ts::shared_mutex reload_mutex; + ts::shared_mutex wd_mutex; private: char *_secret = nullptr; @@ -504,6 +606,8 @@ class S3Config bool _virt_host_modified = false; TSCont _cont = nullptr; TSCont _conf_rld = nullptr; + TSCont _conf_watch = nullptr; + TSCont _dir_watch = nullptr; TSAction _conf_rld_act = nullptr; StringSet _v4includeHeaders; bool _v4includeHeaders_modified = false; @@ -514,6 +618,10 @@ class S3Config long _expiration = 0; char *_conf_fname = nullptr; int _conf_reload_count = 0; + bool _watch_config = false; + std::optional _config_file_wd; + std::optional _config_dir_wd; + int _ttl = 60; }; bool @@ -577,6 +685,10 @@ S3Config::parse_config(const std::string &config_fname) set_region_map(val_str.c_str()); } else if (key_str == "expiration") { set_expiration(val_str.c_str()); + } else if (key_str == "ttl") { + set_ttl(val_str.c_str()); + } else if (key_str == "watch-config") { + set_watch_config(); } else { // ToDo: warnings? } @@ -611,7 +723,7 @@ ConfigCache::get(const char *fname) if (it != _cache.end()) { unsigned update_status = it->second.update_status; - if (tv.tv_sec > (it->second.load_time + _ttl)) { + if (tv.tv_sec > (it->second.load_time + it->second.ttl)) { if (!(update_status & 1) && it->second.update_status.compare_exchange_strong(update_status, update_status + 1)) { TSDebug(PLUGIN_NAME, "Configuration from %s is stale, reloading", config_fname.c_str()); s3 = new S3Config(false); // false == this config does not get the continuation @@ -624,10 +736,14 @@ ConfigCache::get(const char *fname) s3 = nullptr; TSAssert(!"Configuration parsing / caching failed"); } + TSDebug(PLUGIN_NAME, "Updated rule: access_key=%s, virtual_host=%s, version=%d", s3->keyid(), + s3->virt_host() ? "yes" : "no", s3->version()); delete it->second.config; it->second.config = s3; it->second.load_time = tv.tv_sec; + it->second.ttl = s3->ttl(); + TSDebug(PLUGIN_NAME, "Config ttl updated to %d seconds", it->second.ttl.load()); // Update is complete. ++it->second.update_status; @@ -649,10 +765,12 @@ ConfigCache::get(const char *fname) // Create a new cached file. s3 = new S3Config(false); // false == this config does not get the continuation - TSDebug(PLUGIN_NAME, "Parsing and caching configuration from %s, version:%d", config_fname.c_str(), s3->version()); + TSDebug(PLUGIN_NAME, "Parsing and caching configuration from %s", config_fname.c_str()); if (s3->parse_config(config_fname)) { s3->set_conf_fname(fname); - _cache.emplace(config_fname, _ConfigData(s3, tv.tv_sec)); + _cache.emplace(config_fname, _ConfigData(s3, tv.tv_sec, s3->ttl())); + _cache[config_fname].ttl = s3->ttl(); + TSDebug(PLUGIN_NAME, "Config ttl set to %d seconds", _cache[config_fname].ttl.load()); } else { delete s3; s3 = nullptr; @@ -1047,6 +1165,51 @@ cal_reload_delay(long time_diff) } } +int +config_dir_watch(TSCont cont, TSEvent event, void *edata) +{ + TSDebug(PLUGIN_NAME, "config directory watch handler"); + S3Config *s3 = static_cast(TSContDataGet(cont)); + TSAssert(edata != nullptr); + TSFileWatchData *fwd = reinterpret_cast(edata); + + if (event == TS_EVENT_FILE_IGNORED) { + TSDebug(PLUGIN_NAME, "Config directory lost. No longer watching for config changes."); + // Lost the config file's directory. We currently can't deal with this. Just stop watching for file changes. + s3->config_dir_watch_ignored(fwd->wd); + return TS_SUCCESS; + } + + TSAssert(event == TS_EVENT_FILE_CREATED); + TSDebug(PLUGIN_NAME, "File created: %s", fwd->name); + if (strncmp(s3->conf_fname(), fwd->name, strlen(s3->conf_fname())) == 0) { + TSDebug(PLUGIN_NAME, "config file created"); + config_reloader(cont, event, edata); + } + + return TS_SUCCESS; +} + +int +config_watch(TSCont cont, TSEvent event, void *edata) +{ + TSDebug(PLUGIN_NAME, "config watch handler"); + TSAssert(edata != nullptr); + TSFileWatchData *fwd = reinterpret_cast(edata); + + S3Config *s3 = static_cast(TSContDataGet(cont)); + if (event == TS_EVENT_FILE_IGNORED) { + TSDebug(PLUGIN_NAME, "Config file watch lost."); + // Probably deleted. Directory watch will see if it's re-created. + s3->config_file_watch_ignored(fwd->wd); + return TS_SUCCESS; + } + + config_reloader(cont, event, edata); + + return TS_SUCCESS; +} + int config_reloader(TSCont cont, TSEvent event, void *edata) { @@ -1084,6 +1247,12 @@ config_reloader(TSCont cont, TSEvent event, void *edata) } } + if (s3->watch_config()) { + s3->start_watch_config(); + } else { + s3->stop_watch_config(); + } + return TS_SUCCESS; } @@ -1124,6 +1293,8 @@ TSRemapNewInstance(int argc, char *argv[], void **ih, char * /* errbuf ATS_UNUSE {const_cast("v4-exclude-headers"), required_argument, nullptr, 'e'}, {const_cast("v4-region-map"), required_argument, nullptr, 'm'}, {const_cast("session_token"), required_argument, nullptr, 't'}, + {const_cast("watch-config"), no_argument, nullptr, 'w'}, + {const_cast("ttl"), no_argument, nullptr, 'T'}, {nullptr, no_argument, nullptr, '\0'}, }; @@ -1171,6 +1342,12 @@ TSRemapNewInstance(int argc, char *argv[], void **ih, char * /* errbuf ATS_UNUSE case 'm': s3->set_region_map(optarg); break; + case 'w': + s3->set_watch_config(); + break; + case 'T': + s3->set_ttl(optarg); + break; } if (opt == -1) { @@ -1207,6 +1384,12 @@ TSRemapNewInstance(int argc, char *argv[], void **ih, char * /* errbuf ATS_UNUSE } } + if (s3->watch_config()) { + s3->start_watch_config(); + } else { + s3->stop_watch_config(); + } + *ih = static_cast(s3); TSDebug(PLUGIN_NAME, "New rule: access_key=%s, virtual_host=%s, version=%d", s3->keyid(), s3->virt_host() ? "yes" : "no", s3->version()); diff --git a/src/traffic_layout/info.cc b/src/traffic_layout/info.cc index a54a1b10f49..7b911793da8 100644 --- a/src/traffic_layout/info.cc +++ b/src/traffic_layout/info.cc @@ -108,6 +108,7 @@ produce_features(bool json) print_feature("TS_USE_EPOLL", TS_USE_EPOLL, json); print_feature("TS_USE_KQUEUE", TS_USE_KQUEUE, json); print_feature("TS_USE_PORT", TS_USE_PORT, json); + print_feature("TS_USE_INOTIFY", TS_USE_INOTIFY, json); print_feature("TS_USE_POSIX_CAP", TS_USE_POSIX_CAP, json); print_feature("TS_USE_TPROXY", TS_USE_TPROXY, json); print_feature("TS_HAS_SO_MARK", TS_HAS_SO_MARK, json); diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc index 1f46cdfdb9d..89fb0917395 100644 --- a/src/traffic_server/InkAPI.cc +++ b/src/traffic_server/InkAPI.cc @@ -28,6 +28,10 @@ #include #include +#if defined(__linux__) +#include +#endif + #include "tscore/ink_platform.h" #include "tscore/ink_base64.h" #include "tscore/PluginUserArgs.h" @@ -75,6 +79,7 @@ #include "I_Machine.h" #include "HttpProxyServerMain.h" #include "shared/overridable_txn_vars.h" +#include "FileChange.h" #include "ts/ts.h" @@ -10429,3 +10434,19 @@ TSHttpTxnPostBufferReaderGet(TSHttpTxn txnp) HttpSM *sm = (HttpSM *)txnp; return (TSIOBufferReader)sm->get_postbuf_clone_reader(); } + +tsapi TSWatchDescriptor +TSFileEventRegister(const char *filename, TSFileWatchKind kind, TSCont contp) +{ + sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS); + sdk_assert(sdk_sanity_check_null_ptr((void *)this_ethread()) == TS_SUCCESS); + + Continuation *pCont = reinterpret_cast(contp); + return fileChangeManager.add(ts::file::path{filename}, kind, pCont); +} + +tsapi void +TSFileEventUnRegister(TSWatchDescriptor wd) +{ + fileChangeManager.remove(wd); +} diff --git a/src/traffic_server/Makefile.inc b/src/traffic_server/Makefile.inc index b908fea376a..c9f002ef3b9 100644 --- a/src/traffic_server/Makefile.inc +++ b/src/traffic_server/Makefile.inc @@ -82,6 +82,7 @@ traffic_server_traffic_server_LDADD = \ $(top_builddir)/iocore/net/libinknet.a \ $(top_builddir)/lib/records/librecords_p.a \ $(top_builddir)/iocore/eventsystem/libinkevent.a \ + $(top_builddir)/iocore/fs/libinkfs.a \ @HWLOC_LIBS@ \ @LIBPCRE@ \ @LIBRESOLV@ \ diff --git a/src/traffic_server/traffic_server.cc b/src/traffic_server/traffic_server.cc index 84c95aa7da6..d09b76981a2 100644 --- a/src/traffic_server/traffic_server.cc +++ b/src/traffic_server/traffic_server.cc @@ -104,6 +104,7 @@ extern "C" int plock(int); #include "tscore/ink_config.h" #include "P_SSLSNI.h" #include "P_SSLClientUtils.h" +#include "FileChange.h" #if TS_USE_QUIC == 1 #include "Http3.h" @@ -2035,6 +2036,9 @@ main(int /* argc ATS_UNUSED */, const char **argv) proxyServerCheck.notify_one(); } + // Spawn a thread to do file system change notification + fileChangeManager.init(); + // !! ET_NET threads start here !! // This means any spawn scheduling must be done before this point. eventProcessor.start(num_of_net_threads, stacksize); diff --git a/tests/README.md b/tests/README.md index e28a6b90751..a97ba0221c3 100644 --- a/tests/README.md +++ b/tests/README.md @@ -321,6 +321,7 @@ ts.Disk.remap_config.AddLine( * TS_HAS_128BIT_CAS * TS_HAS_TESTS * TS_HAS_WCCP + * TS_USE_INOTIFY ### Example ```python diff --git a/tests/gold_tests/pluginTest/s3_auth/gold/s3_auth_basic.gold b/tests/gold_tests/pluginTest/s3_auth/gold/s3_auth_basic.gold new file mode 100644 index 00000000000..539a4481e87 --- /dev/null +++ b/tests/gold_tests/pluginTest/s3_auth/gold/s3_auth_basic.gold @@ -0,0 +1,34 @@ +* Trying 127.0.0.1:61000... +* Connected to 127.0.0.1 (127.0.0.1) port 61000 (#0) +> GET / HTTP/1.1 +> Host: www.example.com +> User-Agent: curl/`` +> Accept: */* +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< Date: `` +< Age: 0 +< Transfer-Encoding: chunked +< Connection: keep-alive +< Server: ATS/9.2.0 +< +{ [5 bytes data] +* Connection #0 to host 127.0.0.1 left intact +* Trying 127.0.0.1:61000... +* Connected to 127.0.0.1 (127.0.0.1) port 61000 (#0) +> GET / HTTP/1.1 +> Host: www.example.com +> User-Agent: curl/`` +> Accept: */* +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< Date: `` +< Age: 0 +< Transfer-Encoding: chunked +< Connection: keep-alive +< Server: ATS/9.2.0 +< +{ [5 bytes data] +* Connection #0 to host 127.0.0.1 left intact diff --git a/tests/gold_tests/pluginTest/s3_auth/gold/traffic_server.gold b/tests/gold_tests/pluginTest/s3_auth/gold/traffic_server.gold new file mode 100644 index 00000000000..19754bf4abc --- /dev/null +++ b/tests/gold_tests/pluginTest/s3_auth/gold/traffic_server.gold @@ -0,0 +1,2 @@ +`` DIAG: (s3_auth) Updated rule: access_key=1111111, virtual_host=no, version=4 +`` \ No newline at end of file diff --git a/tests/gold_tests/pluginTest/s3_auth/rules/region_map.conf b/tests/gold_tests/pluginTest/s3_auth/rules/region_map.conf new file mode 100644 index 00000000000..cb1467c3941 --- /dev/null +++ b/tests/gold_tests/pluginTest/s3_auth/rules/region_map.conf @@ -0,0 +1 @@ +127.0.0.1 : us-east-1 \ No newline at end of file diff --git a/tests/gold_tests/pluginTest/s3_auth/rules/v4-modified.conf b/tests/gold_tests/pluginTest/s3_auth/rules/v4-modified.conf new file mode 100644 index 00000000000..a869b356dcf --- /dev/null +++ b/tests/gold_tests/pluginTest/s3_auth/rules/v4-modified.conf @@ -0,0 +1,4 @@ +access_key=1111111 +secret_key=5555555 +version=4 +ttl=0 \ No newline at end of file diff --git a/tests/gold_tests/pluginTest/s3_auth/rules/v4.conf b/tests/gold_tests/pluginTest/s3_auth/rules/v4.conf new file mode 100644 index 00000000000..3ad8d7a6c0b --- /dev/null +++ b/tests/gold_tests/pluginTest/s3_auth/rules/v4.conf @@ -0,0 +1,4 @@ +access_key=1234567 +secret_key=9999999 +version=4 +ttl=0 \ No newline at end of file diff --git a/tests/gold_tests/pluginTest/s3_auth/s3_auth_basic.test.py b/tests/gold_tests/pluginTest/s3_auth/s3_auth_basic.test.py new file mode 100644 index 00000000000..e270560acc1 --- /dev/null +++ b/tests/gold_tests/pluginTest/s3_auth/s3_auth_basic.test.py @@ -0,0 +1,87 @@ +''' +Test basic s3_auth function +''' +# 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.ContinueOnFail = True + +Test.SkipUnless( + Condition.HasATSFeature('TS_USE_INOTIFY'), +) + +ts = Test.MakeATSProcess("ts") +server = Test.MakeOriginServer("server") + +Test.testName = "s3_auth: watch config" + +# define the request header and the desired response header +request_header = { + "headers": "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n", + "timestamp": "1469733493.993", + "body": "" +} + +# desired response form the origin server +response_header = { + "headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", + "timestamp": "1469733493.993", + "body": "" +} + +# add request/response +server.addResponse("sessionlog.log", request_header, response_header) + +ts.Disk.records_config.update({ + 'proxy.config.diags.debug.enabled': 1, + 'proxy.config.diags.debug.tags': 'FileChange|s3_auth', +}) + +ts.Setup.CopyAs('rules/v4.conf', Test.RunDirectory) +ts.Setup.CopyAs('rules/v4-modified.conf', Test.RunDirectory) +ts.Setup.CopyAs('rules/region_map.conf', Test.RunDirectory) + +ts.Disk.remap_config.AddLine( + 'map http://www.example.com http://127.0.0.1:{0} \ + @plugin=s3_auth.so \ + @pparam=--config @pparam={1}/v4.conf \ + @pparam=--v4-region-map @pparam={1}/region_map.conf \ + @pparam=--watch-config \ + ' + .format(server.Variables.Port, Test.RunDirectory) +) + +# Commands to get the following response headers +# 1. make a request +# 2. modify the config +# 3. make another request +curlRequest = ( + 'curl -s -v -H "Host: www.example.com" http://127.0.0.1:{0};' + 'sleep 1; cp {1}/v4-modified.conf {1}/v4.conf;' + 'sleep 1; curl -s -v -H "Host: www.example.com" http://127.0.0.1:{0};' +) + +# Test Case +tr = Test.AddTestRun() +tr.Processes.Default.Command = curlRequest.format(ts.Variables.port, Test.RunDirectory) +tr.Processes.Default.ReturnCode = 0 +tr.Processes.Default.StartBefore(server) +tr.Processes.Default.StartBefore(ts) +tr.Processes.Default.Streams.stderr = "gold/s3_auth_basic.gold" +tr.StillRunningAfter = server + +ts.Streams.stderr = "gold/traffic_server.gold" +ts.ReturnCode = 0 From a661b2512dd0b7e58d3c10d45ca9251e47f53207 Mon Sep 17 00:00:00 2001 From: Mo Chen Date: Tue, 14 Jun 2022 11:34:25 -0500 Subject: [PATCH 2/4] Add license headers to conf files, rename test --- .../pluginTest/s3_auth/gold/s3_auth_basic.gold | 8 ++++---- .../pluginTest/s3_auth/rules/region_map.conf | 16 ++++++++++++++++ .../pluginTest/s3_auth/rules/v4-modified.conf | 16 ++++++++++++++++ .../gold_tests/pluginTest/s3_auth/rules/v4.conf | 16 ++++++++++++++++ ...asic.test.py => s3_auth_watch_config.test.py} | 2 +- 5 files changed, 53 insertions(+), 5 deletions(-) rename tests/gold_tests/pluginTest/s3_auth/{s3_auth_basic.test.py => s3_auth_watch_config.test.py} (98%) diff --git a/tests/gold_tests/pluginTest/s3_auth/gold/s3_auth_basic.gold b/tests/gold_tests/pluginTest/s3_auth/gold/s3_auth_basic.gold index 539a4481e87..b23a727881a 100644 --- a/tests/gold_tests/pluginTest/s3_auth/gold/s3_auth_basic.gold +++ b/tests/gold_tests/pluginTest/s3_auth/gold/s3_auth_basic.gold @@ -4,7 +4,7 @@ > Host: www.example.com > User-Agent: curl/`` > Accept: */* -> +> * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < Date: `` @@ -12,7 +12,7 @@ < Transfer-Encoding: chunked < Connection: keep-alive < Server: ATS/9.2.0 -< +< { [5 bytes data] * Connection #0 to host 127.0.0.1 left intact * Trying 127.0.0.1:61000... @@ -21,7 +21,7 @@ > Host: www.example.com > User-Agent: curl/`` > Accept: */* -> +> * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < Date: `` @@ -29,6 +29,6 @@ < Transfer-Encoding: chunked < Connection: keep-alive < Server: ATS/9.2.0 -< +< { [5 bytes data] * Connection #0 to host 127.0.0.1 left intact diff --git a/tests/gold_tests/pluginTest/s3_auth/rules/region_map.conf b/tests/gold_tests/pluginTest/s3_auth/rules/region_map.conf index cb1467c3941..0cee9e64782 100644 --- a/tests/gold_tests/pluginTest/s3_auth/rules/region_map.conf +++ b/tests/gold_tests/pluginTest/s3_auth/rules/region_map.conf @@ -1 +1,17 @@ +# +# 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. 127.0.0.1 : us-east-1 \ No newline at end of file diff --git a/tests/gold_tests/pluginTest/s3_auth/rules/v4-modified.conf b/tests/gold_tests/pluginTest/s3_auth/rules/v4-modified.conf index a869b356dcf..4a5fce86057 100644 --- a/tests/gold_tests/pluginTest/s3_auth/rules/v4-modified.conf +++ b/tests/gold_tests/pluginTest/s3_auth/rules/v4-modified.conf @@ -1,3 +1,19 @@ +# +# 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. access_key=1111111 secret_key=5555555 version=4 diff --git a/tests/gold_tests/pluginTest/s3_auth/rules/v4.conf b/tests/gold_tests/pluginTest/s3_auth/rules/v4.conf index 3ad8d7a6c0b..f541c3476f2 100644 --- a/tests/gold_tests/pluginTest/s3_auth/rules/v4.conf +++ b/tests/gold_tests/pluginTest/s3_auth/rules/v4.conf @@ -1,3 +1,19 @@ +# +# 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. access_key=1234567 secret_key=9999999 version=4 diff --git a/tests/gold_tests/pluginTest/s3_auth/s3_auth_basic.test.py b/tests/gold_tests/pluginTest/s3_auth/s3_auth_watch_config.test.py similarity index 98% rename from tests/gold_tests/pluginTest/s3_auth/s3_auth_basic.test.py rename to tests/gold_tests/pluginTest/s3_auth/s3_auth_watch_config.test.py index e270560acc1..1a56543409c 100644 --- a/tests/gold_tests/pluginTest/s3_auth/s3_auth_basic.test.py +++ b/tests/gold_tests/pluginTest/s3_auth/s3_auth_watch_config.test.py @@ -1,5 +1,5 @@ ''' -Test basic s3_auth function +Test s3_auth config change watch function ''' # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file From 1c908921bad854dfb1d56d5f26cfd36d8e3190aa Mon Sep 17 00:00:00 2001 From: Mo Chen Date: Tue, 14 Jun 2022 12:48:23 -0500 Subject: [PATCH 3/4] Remove port from gold test --- .../gold_tests/pluginTest/s3_auth/gold/s3_auth_basic.gold | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/gold_tests/pluginTest/s3_auth/gold/s3_auth_basic.gold b/tests/gold_tests/pluginTest/s3_auth/gold/s3_auth_basic.gold index b23a727881a..a789fd0139e 100644 --- a/tests/gold_tests/pluginTest/s3_auth/gold/s3_auth_basic.gold +++ b/tests/gold_tests/pluginTest/s3_auth/gold/s3_auth_basic.gold @@ -1,5 +1,5 @@ -* Trying 127.0.0.1:61000... -* Connected to 127.0.0.1 (127.0.0.1) port 61000 (#0) +* Trying 127.0.0.1:``... +* Connected to 127.0.0.1 (127.0.0.1) port `` (#0) > GET / HTTP/1.1 > Host: www.example.com > User-Agent: curl/`` @@ -15,8 +15,8 @@ < { [5 bytes data] * Connection #0 to host 127.0.0.1 left intact -* Trying 127.0.0.1:61000... -* Connected to 127.0.0.1 (127.0.0.1) port 61000 (#0) +* Trying 127.0.0.1:``... +* Connected to 127.0.0.1 (127.0.0.1) port `` (#0) > GET / HTTP/1.1 > Host: www.example.com > User-Agent: curl/`` From 2806fd549888dafd23cdf4758bacd5c3c7c87357 Mon Sep 17 00:00:00 2001 From: Mo Chen Date: Thu, 7 Jul 2022 15:12:18 -0500 Subject: [PATCH 4/4] Code Review Changes -Remove unused constant -Newlines --- iocore/fs/FileChange.h | 2 -- tests/gold_tests/pluginTest/s3_auth/gold/traffic_server.gold | 2 +- tests/gold_tests/pluginTest/s3_auth/rules/region_map.conf | 2 +- tests/gold_tests/pluginTest/s3_auth/rules/v4-modified.conf | 2 +- tests/gold_tests/pluginTest/s3_auth/rules/v4.conf | 2 +- 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/iocore/fs/FileChange.h b/iocore/fs/FileChange.h index 40437c221ec..57aa17225e9 100644 --- a/iocore/fs/FileChange.h +++ b/iocore/fs/FileChange.h @@ -47,8 +47,6 @@ struct file_info { Continuation *contp; }; -constexpr int MAX_WATCHES = 10000; - class FileChangeManager { public: diff --git a/tests/gold_tests/pluginTest/s3_auth/gold/traffic_server.gold b/tests/gold_tests/pluginTest/s3_auth/gold/traffic_server.gold index 19754bf4abc..4c41e8d8c9e 100644 --- a/tests/gold_tests/pluginTest/s3_auth/gold/traffic_server.gold +++ b/tests/gold_tests/pluginTest/s3_auth/gold/traffic_server.gold @@ -1,2 +1,2 @@ `` DIAG: (s3_auth) Updated rule: access_key=1111111, virtual_host=no, version=4 -`` \ No newline at end of file +`` diff --git a/tests/gold_tests/pluginTest/s3_auth/rules/region_map.conf b/tests/gold_tests/pluginTest/s3_auth/rules/region_map.conf index 0cee9e64782..1f663336a8b 100644 --- a/tests/gold_tests/pluginTest/s3_auth/rules/region_map.conf +++ b/tests/gold_tests/pluginTest/s3_auth/rules/region_map.conf @@ -14,4 +14,4 @@ # 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. -127.0.0.1 : us-east-1 \ No newline at end of file +127.0.0.1 : us-east-1 diff --git a/tests/gold_tests/pluginTest/s3_auth/rules/v4-modified.conf b/tests/gold_tests/pluginTest/s3_auth/rules/v4-modified.conf index 4a5fce86057..165d0b96309 100644 --- a/tests/gold_tests/pluginTest/s3_auth/rules/v4-modified.conf +++ b/tests/gold_tests/pluginTest/s3_auth/rules/v4-modified.conf @@ -17,4 +17,4 @@ access_key=1111111 secret_key=5555555 version=4 -ttl=0 \ No newline at end of file +ttl=0 diff --git a/tests/gold_tests/pluginTest/s3_auth/rules/v4.conf b/tests/gold_tests/pluginTest/s3_auth/rules/v4.conf index f541c3476f2..822b5346187 100644 --- a/tests/gold_tests/pluginTest/s3_auth/rules/v4.conf +++ b/tests/gold_tests/pluginTest/s3_auth/rules/v4.conf @@ -17,4 +17,4 @@ access_key=1234567 secret_key=9999999 version=4 -ttl=0 \ No newline at end of file +ttl=0