You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by ad...@apache.org on 2022/03/23 10:33:24 UTC

[nifi-minifi-cpp] branch main updated: MINIFICPP-1769 Add propertyValue to agent manifest metadata

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

adebreceni pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git


The following commit(s) were added to refs/heads/main by this push:
     new 05560bf  MINIFICPP-1769 Add propertyValue to agent manifest metadata
05560bf is described below

commit 05560bf9bcf2aa3f476fcac016efd41083c93c09
Author: Gabor Gyimesi <ga...@gmail.com>
AuthorDate: Wed Mar 23 11:32:07 2022 +0100

    MINIFICPP-1769 Add propertyValue to agent manifest metadata
    
    Signed-off-by: Adam Debreceni <ad...@apache.org>
    
    This closes #1281
---
 .../tests/C2ClearCoreComponentStateTest.cpp        |  6 ++--
 .../tests/C2DescribeCoreComponentStateTest.cpp     |  6 +++-
 .../http-curl/tests/C2DescribeManifestTest.cpp     |  6 +++-
 extensions/http-curl/tests/C2JstackTest.cpp        | 10 +++++--
 extensions/http-curl/tests/C2LogHeartbeatTest.cpp  |  2 +-
 extensions/http-curl/tests/C2PauseResumeTest.cpp   |  6 ++--
 .../http-curl/tests/C2VerifyHeartbeatAndStop.cpp   | 34 ++--------------------
 ...cpp => C2VerifyLightweightHeartbeatAndStop.cpp} | 23 ++++-----------
 .../C2VerifyResourceConsumptionInHeartbeat.cpp     | 19 +++++++-----
 extensions/http-curl/tests/CMakeLists.txt          |  4 ++-
 extensions/http-curl/tests/HTTPHandlers.h          |  7 +++++
 .../include/core/state/nodes/AgentInformation.h    | 12 ++++++++
 .../include/core/state/nodes/SupportedOperations.h |  5 ++++
 libminifi/src/FlowController.cpp                   |  3 ++
 libminifi/src/c2/C2Client.cpp                      |  5 ++++
 .../src/core/state/nodes/SupportedOperations.cpp   |  5 ++++
 16 files changed, 86 insertions(+), 67 deletions(-)

diff --git a/extensions/http-curl/tests/C2ClearCoreComponentStateTest.cpp b/extensions/http-curl/tests/C2ClearCoreComponentStateTest.cpp
index 569fb77..37719e8 100644
--- a/extensions/http-curl/tests/C2ClearCoreComponentStateTest.cpp
+++ b/extensions/http-curl/tests/C2ClearCoreComponentStateTest.cpp
@@ -65,7 +65,9 @@ class VerifyC2ClearCoreComponentState : public VerifyC2Base {
 
 class ClearCoreComponentStateHandler: public HeartbeatHandler {
  public:
-  explicit ClearCoreComponentStateHandler(std::atomic_bool& component_cleared_successfully) : component_cleared_successfully_(component_cleared_successfully) {
+  explicit ClearCoreComponentStateHandler(std::atomic_bool& component_cleared_successfully, std::shared_ptr<minifi::Configure> configuration)
+    : HeartbeatHandler(std::move(configuration)),
+      component_cleared_successfully_(component_cleared_successfully) {
   }
 
   void handleHeartbeat(const rapidjson::Document&, struct mg_connection * conn) override {
@@ -145,7 +147,7 @@ int main(int argc, char **argv) {
   const cmd_args args = parse_cmdline_args(argc, argv, "api/heartbeat");
   VerifyC2ClearCoreComponentState harness(component_cleared_successfully);
   harness.setKeyDir(args.key_dir);
-  ClearCoreComponentStateHandler handler(component_cleared_successfully);
+  ClearCoreComponentStateHandler handler(component_cleared_successfully, harness.getConfiguration());
   harness.setUrl(args.url, &handler);
   harness.run(args.test_file);
   return 0;
diff --git a/extensions/http-curl/tests/C2DescribeCoreComponentStateTest.cpp b/extensions/http-curl/tests/C2DescribeCoreComponentStateTest.cpp
index 354e732..77a3ffe 100644
--- a/extensions/http-curl/tests/C2DescribeCoreComponentStateTest.cpp
+++ b/extensions/http-curl/tests/C2DescribeCoreComponentStateTest.cpp
@@ -57,6 +57,10 @@ class VerifyC2DescribeCoreComponentState : public VerifyC2Describe {
 
 class DescribeCoreComponentStateHandler: public HeartbeatHandler {
  public:
+  explicit DescribeCoreComponentStateHandler(std::shared_ptr<minifi::Configure> configuration)
+    : HeartbeatHandler(std::move(configuration)) {
+  }
+
   void handleHeartbeat(const rapidjson::Document&, struct mg_connection * conn) override {
     sendHeartbeatResponse("DESCRIBE", "corecomponentstate", "889345", conn);
   }
@@ -84,7 +88,7 @@ int main(int argc, char **argv) {
   const cmd_args args = parse_cmdline_args(argc, argv, "api/heartbeat");
   VerifyC2DescribeCoreComponentState harness;
   harness.setKeyDir(args.key_dir);
-  DescribeCoreComponentStateHandler handler;
+  DescribeCoreComponentStateHandler handler(harness.getConfiguration());
   harness.setUrl(args.url, &handler);
   harness.run(args.test_file);
   return 0;
diff --git a/extensions/http-curl/tests/C2DescribeManifestTest.cpp b/extensions/http-curl/tests/C2DescribeManifestTest.cpp
index 9e2c496..5c46f5c 100644
--- a/extensions/http-curl/tests/C2DescribeManifestTest.cpp
+++ b/extensions/http-curl/tests/C2DescribeManifestTest.cpp
@@ -25,6 +25,10 @@
 
 class DescribeManifestHandler: public HeartbeatHandler {
  public:
+  explicit DescribeManifestHandler(std::shared_ptr<minifi::Configure> configuration)
+    : HeartbeatHandler(std::move(configuration)) {
+  }
+
   void handleHeartbeat(const rapidjson::Document&, struct mg_connection * conn) override {
     sendHeartbeatResponse("DESCRIBE", "manifest", "889345", conn);
   }
@@ -38,7 +42,7 @@ int main(int argc, char **argv) {
   const cmd_args args = parse_cmdline_args(argc, argv, "heartbeat");
   VerifyC2Describe harness;
   harness.setKeyDir(args.key_dir);
-  DescribeManifestHandler responder;
+  DescribeManifestHandler responder(harness.getConfiguration());
   harness.setUrl(args.url, &responder);
   harness.run(args.test_file);
 }
diff --git a/extensions/http-curl/tests/C2JstackTest.cpp b/extensions/http-curl/tests/C2JstackTest.cpp
index 06c7109..b7cfb8a 100644
--- a/extensions/http-curl/tests/C2JstackTest.cpp
+++ b/extensions/http-curl/tests/C2JstackTest.cpp
@@ -38,7 +38,11 @@ class VerifyC2DescribeJstack : public VerifyC2Describe {
 
 class DescribeJstackHandler : public HeartbeatHandler {
  public:
-  explicit DescribeJstackHandler(std::atomic_bool& acknowledgement_received) : HeartbeatHandler(), acknowledgement_received_(acknowledgement_received) {}
+  explicit DescribeJstackHandler(std::atomic_bool& acknowledgement_received, std::shared_ptr<minifi::Configure> configuration)
+    : HeartbeatHandler(std::move(configuration)),
+      acknowledgement_received_(acknowledgement_received) {
+  }
+
   void handleHeartbeat(const rapidjson::Document&, struct mg_connection * conn) override {
     sendHeartbeatResponse("DESCRIBE", "jstack", "889398", conn);
   }
@@ -54,9 +58,9 @@ class DescribeJstackHandler : public HeartbeatHandler {
 int main(int argc, char **argv) {
   const cmd_args args = parse_cmdline_args(argc, argv, "heartbeat");
   std::atomic_bool acknowledgement_received{ false };
-  VerifyC2DescribeJstack harness{ acknowledgement_received };
+  VerifyC2DescribeJstack harness{acknowledgement_received};
   harness.setKeyDir(args.key_dir);
-  DescribeJstackHandler responder{ acknowledgement_received };
+  DescribeJstackHandler responder{acknowledgement_received, harness.getConfiguration()};
   harness.setUrl(args.url, &responder);
   harness.run(args.test_file);
   return 0;
diff --git a/extensions/http-curl/tests/C2LogHeartbeatTest.cpp b/extensions/http-curl/tests/C2LogHeartbeatTest.cpp
index 09cef80..624185d 100644
--- a/extensions/http-curl/tests/C2LogHeartbeatTest.cpp
+++ b/extensions/http-curl/tests/C2LogHeartbeatTest.cpp
@@ -73,7 +73,7 @@ class VerifyLogC2Heartbeat : public VerifyC2Base {
 
 int main() {
   VerifyLogC2Heartbeat harness;
-  HeartbeatHandler responder;
+  HeartbeatHandler responder(harness.getConfiguration());
   harness.setUrl("https://localhost:0/heartbeat", &responder);
   harness.run();
 }
diff --git a/extensions/http-curl/tests/C2PauseResumeTest.cpp b/extensions/http-curl/tests/C2PauseResumeTest.cpp
index 1314cde..d4cbbf8 100644
--- a/extensions/http-curl/tests/C2PauseResumeTest.cpp
+++ b/extensions/http-curl/tests/C2PauseResumeTest.cpp
@@ -55,7 +55,9 @@ class PauseResumeHandler: public HeartbeatHandler {
   static const uint32_t PAUSE_SECONDS = 3;
   static const uint32_t INITIAL_GET_INVOKE_COUNT = 2;
 
-  explicit PauseResumeHandler(std::atomic_bool& flow_resumed_successfully) : HeartbeatHandler(), flow_resumed_successfully_(flow_resumed_successfully) {}
+  explicit PauseResumeHandler(std::atomic_bool& flow_resumed_successfully, std::shared_ptr<minifi::Configure> configuration)
+    : HeartbeatHandler(std::move(configuration)), flow_resumed_successfully_(flow_resumed_successfully) {
+  }
   bool handleGet(CivetServer* /*server*/, struct mg_connection* conn) override {
     assert(flow_state_ != FlowState::PAUSED);
     ++get_invoke_count_;
@@ -113,7 +115,7 @@ int main(int argc, char **argv) {
   std::atomic_bool flow_resumed_successfully{false};
   VerifyC2PauseResume harness{flow_resumed_successfully};
   harness.setKeyDir(args.key_dir);
-  PauseResumeHandler responder{flow_resumed_successfully};
+  PauseResumeHandler responder{flow_resumed_successfully, harness.getConfiguration()};
 
   std::shared_ptr<core::Repository> test_repo = std::make_shared<TestRepository>();
   std::shared_ptr<core::Repository> test_flow_repo = std::make_shared<TestFlowRepository>();
diff --git a/extensions/http-curl/tests/C2VerifyHeartbeatAndStop.cpp b/extensions/http-curl/tests/C2VerifyHeartbeatAndStop.cpp
index 2fe629f..64e071a 100644
--- a/extensions/http-curl/tests/C2VerifyHeartbeatAndStop.cpp
+++ b/extensions/http-curl/tests/C2VerifyHeartbeatAndStop.cpp
@@ -28,21 +28,6 @@
 #include "utils/IntegrationTestUtils.h"
 #include "properties/Configuration.h"
 
-class LightWeightC2Handler : public HeartbeatHandler {
- public:
-  void handleHeartbeat(const rapidjson::Document& root, struct mg_connection *) override {
-    if (calls_ == 0) {
-      verifyJsonHasAgentManifest(root);
-    } else {
-      assert(root.HasMember("agentInfo"));
-      assert(!root["agentInfo"].HasMember("agentManifest"));
-    }
-    calls_++;
-  }
- private:
-  std::atomic<size_t> calls_{0};
-};
-
 class VerifyC2Heartbeat : public VerifyC2Base {
  public:
   void testSetup() override {
@@ -66,26 +51,11 @@ class VerifyC2Heartbeat : public VerifyC2Base {
   }
 };
 
-class VerifyLightWeightC2Heartbeat : public VerifyC2Heartbeat {
- public:
-  void configureFullHeartbeat() override {
-    configuration->set(minifi::Configuration::nifi_c2_full_heartbeat, "false");
-  }
-};
-
 int main(int argc, char **argv) {
   const cmd_args args = parse_cmdline_args(argc, argv, "heartbeat");
-  {
-    VerifyC2Heartbeat harness;
-    harness.setKeyDir(args.key_dir);
-    HeartbeatHandler responder;
-    harness.setUrl(args.url, &responder);
-    harness.run(args.test_file);
-  }
-
-  VerifyLightWeightC2Heartbeat harness;
+  VerifyC2Heartbeat harness;
   harness.setKeyDir(args.key_dir);
-  LightWeightC2Handler responder;
+  HeartbeatHandler responder(harness.getConfiguration());
   harness.setUrl(args.url, &responder);
   harness.run(args.test_file);
 
diff --git a/extensions/http-curl/tests/C2VerifyHeartbeatAndStop.cpp b/extensions/http-curl/tests/C2VerifyLightweightHeartbeatAndStop.cpp
similarity index 85%
copy from extensions/http-curl/tests/C2VerifyHeartbeatAndStop.cpp
copy to extensions/http-curl/tests/C2VerifyLightweightHeartbeatAndStop.cpp
index 2fe629f..4b6c313 100644
--- a/extensions/http-curl/tests/C2VerifyHeartbeatAndStop.cpp
+++ b/extensions/http-curl/tests/C2VerifyLightweightHeartbeatAndStop.cpp
@@ -30,6 +30,10 @@
 
 class LightWeightC2Handler : public HeartbeatHandler {
  public:
+  explicit LightWeightC2Handler(std::shared_ptr<minifi::Configure> configuration)
+    : HeartbeatHandler(std::move(configuration)) {
+  }
+
   void handleHeartbeat(const rapidjson::Document& root, struct mg_connection *) override {
     if (calls_ == 0) {
       verifyJsonHasAgentManifest(root);
@@ -43,7 +47,7 @@ class LightWeightC2Handler : public HeartbeatHandler {
   std::atomic<size_t> calls_{0};
 };
 
-class VerifyC2Heartbeat : public VerifyC2Base {
+class VerifyLightWeightC2Heartbeat : public VerifyC2Base {
  public:
   void testSetup() override {
     LogTestController::getInstance().setTrace<minifi::c2::C2Agent>();
@@ -62,30 +66,15 @@ class VerifyC2Heartbeat : public VerifyC2Base {
   }
 
   void configureFullHeartbeat() override {
-    configuration->set(minifi::Configuration::nifi_c2_full_heartbeat, "true");
-  }
-};
-
-class VerifyLightWeightC2Heartbeat : public VerifyC2Heartbeat {
- public:
-  void configureFullHeartbeat() override {
     configuration->set(minifi::Configuration::nifi_c2_full_heartbeat, "false");
   }
 };
 
 int main(int argc, char **argv) {
   const cmd_args args = parse_cmdline_args(argc, argv, "heartbeat");
-  {
-    VerifyC2Heartbeat harness;
-    harness.setKeyDir(args.key_dir);
-    HeartbeatHandler responder;
-    harness.setUrl(args.url, &responder);
-    harness.run(args.test_file);
-  }
-
   VerifyLightWeightC2Heartbeat harness;
   harness.setKeyDir(args.key_dir);
-  LightWeightC2Handler responder;
+  LightWeightC2Handler responder(harness.getConfiguration());
   harness.setUrl(args.url, &responder);
   harness.run(args.test_file);
 
diff --git a/extensions/http-curl/tests/C2VerifyResourceConsumptionInHeartbeat.cpp b/extensions/http-curl/tests/C2VerifyResourceConsumptionInHeartbeat.cpp
index 9cae9cf..c329abb 100644
--- a/extensions/http-curl/tests/C2VerifyResourceConsumptionInHeartbeat.cpp
+++ b/extensions/http-curl/tests/C2VerifyResourceConsumptionInHeartbeat.cpp
@@ -32,6 +32,10 @@
 
 class ResourceConsumptionInHeartbeatHandler : public HeartbeatHandler {
  public:
+  explicit ResourceConsumptionInHeartbeatHandler(std::shared_ptr<minifi::Configure> configuration)
+    : HeartbeatHandler(std::move(configuration)) {
+  }
+
   void handleHeartbeat(const rapidjson::Document& root, struct mg_connection *) override {
     verifySystemResourceConsumption(root, (calls_ == 0));
     verifyProcessResourceConsumption(root, (calls_ == 0));
@@ -97,10 +101,6 @@ class ResourceConsumptionInHeartbeatHandler : public HeartbeatHandler {
 
 class VerifyResourceConsumptionInHeartbeat : public VerifyC2Base {
  public:
-  explicit VerifyResourceConsumptionInHeartbeat(std::function<bool()> event_to_wait_for) :
-      VerifyC2Base(), event_to_wait_for_(event_to_wait_for) {
-  }
-
   void testSetup() override {
     LogTestController::getInstance().setTrace<minifi::c2::C2Agent>();
     LogTestController::getInstance().setDebug<minifi::c2::RESTSender>();
@@ -118,18 +118,23 @@ class VerifyResourceConsumptionInHeartbeat : public VerifyC2Base {
     configuration->set(minifi::Configuration::nifi_c2_full_heartbeat, "false");
   }
 
+  void setEventToWaitFor(std::function<bool()> event_to_wait_for) {
+    event_to_wait_for_ = event_to_wait_for;
+  }
+
   std::function<bool()> event_to_wait_for_;
 };
 
 int main(int argc, char **argv) {
   const cmd_args args = parse_cmdline_args(argc, argv, "heartbeat");
-
-  ResourceConsumptionInHeartbeatHandler responder;
+  VerifyResourceConsumptionInHeartbeat harness;
+  ResourceConsumptionInHeartbeatHandler responder(harness.getConfiguration());
   auto event_to_wait_for = [&responder] {
     return responder.getNumberOfHandledHeartBeats() >= 3;
   };
-  VerifyResourceConsumptionInHeartbeat harness(event_to_wait_for);
+
   harness.setUrl(args.url, &responder);
+  harness.setEventToWaitFor(event_to_wait_for);
   harness.run(args.test_file);
 
   return 0;
diff --git a/extensions/http-curl/tests/CMakeLists.txt b/extensions/http-curl/tests/CMakeLists.txt
index 3fed4bd..0077008 100644
--- a/extensions/http-curl/tests/CMakeLists.txt
+++ b/extensions/http-curl/tests/CMakeLists.txt
@@ -79,6 +79,7 @@ add_test(NAME C2RequestClassTest COMMAND C2RequestClassTest)
 if (NOT OPENSSL_OFF)
 	add_test(NAME VerifyInvokeHTTPGetTestSecure COMMAND VerifyInvokeHTTPGetTest "${TEST_RESOURCES}/TestHTTPGetSecure.yml"  "${TEST_RESOURCES}/")
 	add_test(NAME C2VerifyHeartbeatAndStopSecure COMMAND C2VerifyHeartbeatAndStop "${TEST_RESOURCES}/C2VerifyHeartbeatAndStopSecure.yml" "${TEST_RESOURCES}/")
+	add_test(NAME C2VerifyLightweightHeartbeatAndStopSecure COMMAND C2VerifyLightweightHeartbeatAndStop "${TEST_RESOURCES}/C2VerifyHeartbeatAndStopSecure.yml" "${TEST_RESOURCES}/")
 	add_test(NAME VerifyInvokeHTTPPostTestSecure COMMAND VerifyInvokeHTTPPostTest "${TEST_RESOURCES}/TestInvokeHTTPPostSecure.yml" "${TEST_RESOURCES}/")
 endif()
 add_test(NAME HttpPostIntegrationTest COMMAND HttpPostIntegrationTest "${TEST_RESOURCES}/TestHTTPPost.yml" "${TEST_RESOURCES}/")
@@ -86,7 +87,8 @@ if (NOT APPLE)
 	add_test(NAME HttpPostIntegrationTestChunked COMMAND HttpPostIntegrationTest "${TEST_RESOURCES}/TestHTTPPostChunkedEncoding.yml" "${TEST_RESOURCES}/")
 endif()
 add_test(NAME C2VerifyServeResults COMMAND C2VerifyServeResults "${TEST_RESOURCES}/C2VerifyServeResults.yml" "${TEST_RESOURCES}/")
-add_test(NAME C2VerifyHeartbeatAndStop COMMAND C2VerifyHeartbeatAndStop "${TEST_RESOURCES}/C2VerifyHeartbeatAndStop.yml" )
+add_test(NAME C2VerifyHeartbeatAndStop COMMAND C2VerifyHeartbeatAndStop "${TEST_RESOURCES}/C2VerifyHeartbeatAndStop.yml")
+add_test(NAME C2VerifyLightweightHeartbeatAndStop COMMAND C2VerifyLightweightHeartbeatAndStop "${TEST_RESOURCES}/C2VerifyHeartbeatAndStop.yml")
 add_test(NAME C2VerifyResourceConsumptionInHeartbeat COMMAND C2VerifyResourceConsumptionInHeartbeat "${TEST_RESOURCES}/C2VerifyHeartbeatAndStop.yml")
 add_test(NAME HTTPSiteToSiteTests COMMAND HTTPSiteToSiteTests "${TEST_RESOURCES}/TestHTTPSiteToSite.yml" "${TEST_RESOURCES}/" "http://localhost:8099/nifi-api")
 add_test(NAME TimeoutHTTPSiteToSiteTests COMMAND TimeoutHTTPSiteToSiteTests "${TEST_RESOURCES}/TestTimeoutHTTPSiteToSite.yml" "${TEST_RESOURCES}/" "http://localhost:8098/nifi-api")
diff --git a/extensions/http-curl/tests/HTTPHandlers.h b/extensions/http-curl/tests/HTTPHandlers.h
index 25ebbc0..c5b6c2e 100644
--- a/extensions/http-curl/tests/HTTPHandlers.h
+++ b/extensions/http-curl/tests/HTTPHandlers.h
@@ -388,6 +388,8 @@ std::string readPayload(struct mg_connection *conn) {
 
 class HeartbeatHandler : public ServerAwareHandler {
  public:
+  explicit HeartbeatHandler(std::shared_ptr<minifi::Configure> configuration) : configuration_(std::move(configuration)) {}
+
   virtual void handleHeartbeat(const rapidjson::Document& root, struct mg_connection *) {
     verifyJsonHasAgentManifest(root);
   }
@@ -531,6 +533,9 @@ class HeartbeatHandler : public ServerAwareHandler {
           std::unordered_map<std::string, std::string> config_property;
           if (ranges::find(disallowed_properties, property.name) == ranges::end(disallowed_properties)) {
             config_property.emplace("propertyName", property.name);
+            if (auto value = configuration_->get(std::string(property.name))) {
+              config_property.emplace("propertyValue", *value);
+            }
             config_property.emplace("validator", property.validator->getName());
             config_properties.push_back(config_property);
           }
@@ -600,6 +605,8 @@ class HeartbeatHandler : public ServerAwareHandler {
       }
     }
   }
+
+  std::shared_ptr<minifi::Configure> configuration_;
 };
 
 class C2FlowProvider : public ServerAwareHandler {
diff --git a/libminifi/include/core/state/nodes/AgentInformation.h b/libminifi/include/core/state/nodes/AgentInformation.h
index 1f5669d..49c3129 100644
--- a/libminifi/include/core/state/nodes/AgentInformation.h
+++ b/libminifi/include/core/state/nodes/AgentInformation.h
@@ -621,6 +621,10 @@ class AgentManifest : public DeviceInformation {
     update_policy_controller_ = update_policy_controller;
   }
 
+  void setConfigurationReader(std::function<std::optional<std::string>(const std::string&)> configuration_reader) {
+    configuration_reader_ = configuration_reader;
+  }
+
   std::vector<SerializedResponseNode> serialize() {
     static std::vector<SerializedResponseNode> serialized;
     if (serialized.empty()) {
@@ -688,6 +692,7 @@ class AgentManifest : public DeviceInformation {
       SupportedOperations supported_operations("supportedOperations");
       supported_operations.setStateMonitor(monitor_);
       supported_operations.setUpdatePolicyController(update_policy_controller_);
+      supported_operations.setConfigurationReader(configuration_reader_);
       for (const auto& operation : supported_operations.serialize()) {
         serialized.push_back(operation);
       }
@@ -698,6 +703,7 @@ class AgentManifest : public DeviceInformation {
  private:
   state::StateMonitor* monitor_ = nullptr;
   controllers::UpdatePolicyControllerService* update_policy_controller_ = nullptr;
+  std::function<std::optional<std::string>(const std::string&)> configuration_reader_;
 };
 
 class AgentNode : public DeviceInformation, public AgentMonitor, public AgentIdentifier {
@@ -716,6 +722,10 @@ class AgentNode : public DeviceInformation, public AgentMonitor, public AgentIde
     update_policy_controller_ = update_policy_controller;
   }
 
+  void setConfigurationReader(std::function<std::optional<std::string>(const std::string&)> configuration_reader) {
+    configuration_reader_ = configuration_reader;
+  }
+
  protected:
   std::vector<SerializedResponseNode> serialize() {
     std::vector<SerializedResponseNode> serialized;
@@ -748,6 +758,7 @@ class AgentNode : public DeviceInformation, public AgentMonitor, public AgentIde
     AgentManifest manifest{"manifest"};
     manifest.setStateMonitor(monitor_);
     manifest.setUpdatePolicyController(update_policy_controller_);
+    manifest.setConfigurationReader(configuration_reader_);
     agentManifest.children = manifest.serialize();
     return std::vector<SerializedResponseNode>{ agentManifest };
   }
@@ -780,6 +791,7 @@ class AgentNode : public DeviceInformation, public AgentMonitor, public AgentIde
  private:
   std::optional<std::string> agentManifestHash_;
   controllers::UpdatePolicyControllerService* update_policy_controller_ = nullptr;
+  std::function<std::optional<std::string>(const std::string&)> configuration_reader_;
 };
 
 /**
diff --git a/libminifi/include/core/state/nodes/SupportedOperations.h b/libminifi/include/core/state/nodes/SupportedOperations.h
index 0291811..0c283c1 100644
--- a/libminifi/include/core/state/nodes/SupportedOperations.h
+++ b/libminifi/include/core/state/nodes/SupportedOperations.h
@@ -44,6 +44,10 @@ class SupportedOperations : public DeviceInformation {
     update_policy_controller_ = update_policy_controller;
   }
 
+  void setConfigurationReader(std::function<std::optional<std::string>(const std::string&)> configuration_reader) {
+    configuration_reader_ = configuration_reader;
+  }
+
  private:
   using Metadata = std::unordered_map<std::string, std::vector<std::unordered_map<std::string, std::string>>>;
 
@@ -65,6 +69,7 @@ class SupportedOperations : public DeviceInformation {
 
   state::StateMonitor* monitor_ = nullptr;
   controllers::UpdatePolicyControllerService* update_policy_controller_ = nullptr;
+  std::function<std::optional<std::string>(const std::string&)> configuration_reader_;
 };
 
 }  // namespace org::apache::nifi::minifi::state::response
diff --git a/libminifi/src/FlowController.cpp b/libminifi/src/FlowController.cpp
index 0962cec..516ff8f 100644
--- a/libminifi/src/FlowController.cpp
+++ b/libminifi/src/FlowController.cpp
@@ -434,6 +434,9 @@ std::shared_ptr<state::response::ResponseNode> FlowController::getAgentManifest(
   auto agentInfo = std::make_shared<state::response::AgentInformation>("agentInfo");
   agentInfo->setUpdatePolicyController(std::static_pointer_cast<controllers::UpdatePolicyControllerService>(getControllerService(c2::C2Agent::UPDATE_NAME)).get());
   agentInfo->setAgentIdentificationProvider(configuration_);
+  agentInfo->setConfigurationReader([this](const std::string& key){
+    return configuration_->get(key);
+  });
   agentInfo->includeAgentStatus(false);
   return agentInfo;
 }
diff --git a/libminifi/src/c2/C2Client.cpp b/libminifi/src/c2/C2Client.cpp
index 3706574..a4d51fc 100644
--- a/libminifi/src/c2/C2Client.cpp
+++ b/libminifi/src/c2/C2Client.cpp
@@ -109,6 +109,11 @@ void C2Client::initialize(core::controller::ControllerServiceProvider *controlle
       if (agent_node != nullptr && controller != nullptr) {
         agent_node->setUpdatePolicyController(std::static_pointer_cast<controllers::UpdatePolicyControllerService>(controller->getControllerService(C2Agent::UPDATE_NAME)).get());
       }
+      if (agent_node != nullptr) {
+        agent_node->setConfigurationReader([this](const std::string& key){
+          return configuration_->get(key);
+        });
+      }
       auto configuration_checksums = dynamic_cast<state::response::ConfigurationChecksums*>(response_node.get());
       if (configuration_checksums) {
         configuration_checksums->addChecksumCalculator(configuration_->getChecksumCalculator());
diff --git a/libminifi/src/core/state/nodes/SupportedOperations.cpp b/libminifi/src/core/state/nodes/SupportedOperations.cpp
index dce6625..8c893c7 100644
--- a/libminifi/src/core/state/nodes/SupportedOperations.cpp
+++ b/libminifi/src/core/state/nodes/SupportedOperations.cpp
@@ -70,6 +70,11 @@ SupportedOperations::Metadata SupportedOperations::buildUpdatePropertiesMetadata
       std::unordered_map<std::string, std::string> property;
       property.emplace("propertyName", config_property.name);
       property.emplace("validator", config_property.validator->getName());
+      if (configuration_reader_) {
+        if (auto property_value = configuration_reader_(std::string(config_property.name))) {
+          property.emplace("propertyValue", *property_value);
+        }
+      }
       supported_config_updates.push_back(property);
     }
   }