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

szaszm 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 271ac906d MINIFICPP-2509 Add option to reload parameter contexts from 
parameter providers on restart
271ac906d is described below

commit 271ac906d5c963d6c3287faf02331ab4283df26f
Author: Gabor Gyimesi <[email protected]>
AuthorDate: Thu Apr 17 11:01:19 2025 +0200

    MINIFICPP-2509 Add option to reload parameter contexts from parameter 
providers on restart
    
    Closes #1915
    
    Signed-off-by: Marton Szasz <[email protected]>
---
 CONFIGURE.md                                       |  3 +-
 libminifi/include/core/ParameterProvider.h         | 13 +++-
 libminifi/include/core/json/JsonFlowSerializer.h   |  4 +-
 libminifi/include/core/yaml/YamlFlowSerializer.h   |  4 +-
 libminifi/src/core/ParameterProvider.cpp           | 15 +++-
 .../src/core/flow/StructuredConfiguration.cpp      |  7 +-
 libminifi/src/core/json/JsonFlowSerializer.cpp     | 24 +++---
 libminifi/src/core/yaml/YamlFlowSerializer.cpp     | 28 +++----
 libminifi/test/unit/JsonFlowSerializerTests.cpp    | 89 ++++++++++++++++++++++
 libminifi/test/unit/YamlFlowSerializerTests.cpp    | 73 ++++++++++++++++++
 10 files changed, 221 insertions(+), 39 deletions(-)

diff --git a/CONFIGURE.md b/CONFIGURE.md
index ae7273c6d..aae1d5cc1 100644
--- a/CONFIGURE.md
+++ b/CONFIGURE.md
@@ -257,10 +257,11 @@ Parameter Context Name: root-process-group-context
 
 Parameter contexts can be generated by Parameter Providers. Parameter 
Providers can be added to the flow configuration, after which parameter 
contexts and parameters generated by these providers can be referenced in the 
properties. The parameter contexts generated are persisted in the flow 
configuration file and are only regenerated on MiNiFi C++ restart if the 
context is removed from the flow configuration. Other parameter contexts can be 
also inherited from provider generated parameter [...]
 
-There are two properties that can be set for all parameter providers for 
selecting which properties should be sensitive parameters:
+The following properties can be set for all parameter providers:
 
 - `Sensitive Parameter Scope`: This property can be set to `none`, `selected` 
or `all`. If set to `All`, all parameters generated by the provider will be 
marked as sensitive. If set to `none`, all parameters generated by the provider 
will be marked as non-sensitive. If set to `selected`, the `Sensitive Parameter 
List` property should be set to a list of parameter names that should be marked 
as sensitive.
 - `Sensitive Parameter List`: This property should be set to a comma-separated 
list of parameter names that should be marked as sensitive. This property is 
only used if the `Sensitive Parameter Scope` property is set to `selected`.
+- `Reload Values On Restart`: If set to `true`, parameter contexts and their 
values generated by the parameter provider will be reloaded on MiNiFi C++ 
restart even if the parameter context already exists in the flow configuration.
 
 An example for using parameter providers in a JSON configuration file:
 
diff --git a/libminifi/include/core/ParameterProvider.h 
b/libminifi/include/core/ParameterProvider.h
index c09220671..d7b87b091 100644
--- a/libminifi/include/core/ParameterProvider.h
+++ b/libminifi/include/core/ParameterProvider.h
@@ -40,7 +40,7 @@ enum class SensitiveParameterScopeOptions {
   selected
 };
 
-struct ParameterProviderConfig {
+struct SensitiveParameterConfig {
   SensitiveParameterScopeOptions sensitive_parameter_scope = 
SensitiveParameterScopeOptions::none;
   std::unordered_set<std::string> sensitive_parameters;
 
@@ -68,16 +68,23 @@ class ParameterProvider : public ConfigurableComponentImpl, 
public CoreComponent
   MINIFIAPI static constexpr auto SensitiveParameterList = 
core::PropertyDefinitionBuilder<>::createProperty("Sensitive Parameter List")
       .withDescription("List of sensitive parameters, if 'Sensitive Parameter 
Scope' is set to 'selected'.")
       .build();
+  MINIFIAPI static constexpr auto ReloadValuesOnRestart = 
core::PropertyDefinitionBuilder<>::createProperty("Reload Values On Restart")
+      .withDescription("Reload provider-generated parameter context values 
when MiNiFi is restarted")
+      .withValidator(core::StandardPropertyValidators::BOOLEAN_VALIDATOR)
+      .withDefaultValue("false")
+      .isRequired(true)
+      .build();
 
-  MINIFIAPI static constexpr auto Properties = 
std::to_array<core::PropertyReference>({SensitiveParameterScope, 
SensitiveParameterList});
+  MINIFIAPI static constexpr auto Properties = 
std::to_array<core::PropertyReference>({SensitiveParameterScope, 
SensitiveParameterList, ReloadValuesOnRestart});
 
   bool supportsDynamicProperties() const override { return false; }
   bool supportsDynamicRelationships() const override { return false; };
 
+  bool reloadValuesOnRestart() const;
   std::vector<gsl::not_null<std::unique_ptr<ParameterContext>>> 
createParameterContexts();
 
  protected:
-  ParameterProviderConfig readParameterProviderConfig() const;
+  SensitiveParameterConfig readSensitiveParameterConfig() const;
   virtual std::vector<ParameterGroup> buildParameterGroups() = 0;
 
   bool canEdit() override { return true; }
diff --git a/libminifi/include/core/json/JsonFlowSerializer.h 
b/libminifi/include/core/json/JsonFlowSerializer.h
index c8929f0c0..abebabe25 100644
--- a/libminifi/include/core/json/JsonFlowSerializer.h
+++ b/libminifi/include/core/json/JsonFlowSerializer.h
@@ -33,8 +33,8 @@ class JsonFlowSerializer : public core::flow::FlowSerializer {
       const std::unordered_map<std::string, 
gsl::not_null<std::unique_ptr<ParameterContext>>>& parameter_contexts) const 
override;
 
  private:
-  void addProviderCreatedParameterContexts(rapidjson::Value& 
flow_definition_json, rapidjson::Document::AllocatorType& alloc, const 
core::flow::FlowSchema& schema,
-    const std::unordered_map<std::string, 
gsl::not_null<std::unique_ptr<ParameterContext>>>& parameter_contexts) const;
+  static void addProviderCreatedParameterContexts(rapidjson::Value& 
flow_definition_json, rapidjson::Document::AllocatorType& alloc, const 
core::flow::FlowSchema& schema,
+    const std::unordered_map<std::string, 
gsl::not_null<std::unique_ptr<ParameterContext>>>& parameter_contexts);
   void encryptSensitiveParameters(rapidjson::Value& flow_definition_json, 
rapidjson::Document::AllocatorType& alloc, const core::flow::FlowSchema& schema,
       const utils::crypto::EncryptionProvider& encryption_provider, const 
std::unordered_map<utils::Identifier, core::flow::Overrides>& overrides) const;
   void encryptSensitiveProcessorProperties(rapidjson::Value& root_group, 
rapidjson::Document::AllocatorType& alloc, const core::ProcessGroup& 
process_group,
diff --git a/libminifi/include/core/yaml/YamlFlowSerializer.h 
b/libminifi/include/core/yaml/YamlFlowSerializer.h
index dae6cd2aa..81afd109e 100644
--- a/libminifi/include/core/yaml/YamlFlowSerializer.h
+++ b/libminifi/include/core/yaml/YamlFlowSerializer.h
@@ -30,8 +30,8 @@ class YamlFlowSerializer : public core::flow::FlowSerializer {
       const std::unordered_map<std::string, 
gsl::not_null<std::unique_ptr<ParameterContext>>>& parameter_contexts) const 
override;
 
  private:
-  void addProviderCreatedParameterContexts(YAML::Node flow_definition_yaml, 
const core::flow::FlowSchema& schema,
-    const std::unordered_map<std::string, 
gsl::not_null<std::unique_ptr<ParameterContext>>>& parameter_contexts) const;
+  static void addProviderCreatedParameterContexts(YAML::Node 
flow_definition_yaml, const core::flow::FlowSchema& schema,
+    const std::unordered_map<std::string, 
gsl::not_null<std::unique_ptr<ParameterContext>>>& parameter_contexts);
   void encryptSensitiveParameters(YAML::Node& flow_definition_yaml, const 
core::flow::FlowSchema& schema, const utils::crypto::EncryptionProvider& 
encryption_provider,
     const std::unordered_map<utils::Identifier, core::flow::Overrides>& 
overrides) const;
   void encryptSensitiveProcessorProperties(YAML::Node& flow_definition_yaml, 
const core::ProcessGroup& process_group, const core::flow::FlowSchema& schema,
diff --git a/libminifi/src/core/ParameterProvider.cpp 
b/libminifi/src/core/ParameterProvider.cpp
index 22d067309..e7ff3b82c 100644
--- a/libminifi/src/core/ParameterProvider.cpp
+++ b/libminifi/src/core/ParameterProvider.cpp
@@ -19,8 +19,17 @@
 
 namespace org::apache::nifi::minifi::core {
 
-ParameterProviderConfig ParameterProvider::readParameterProviderConfig() const 
{
-  ParameterProviderConfig config;
+bool ParameterProvider::reloadValuesOnRestart() const {
+  if (auto reload_values_on_restart_str = 
getProperty(ReloadValuesOnRestart.name)) {
+    if (auto reload_values_on_restart = 
parsing::parseBool(*reload_values_on_restart_str)) {
+      return reload_values_on_restart.value();
+    }
+  }
+  throw ParameterException("Reload Values On Restart property is required");
+}
+
+SensitiveParameterConfig ParameterProvider::readSensitiveParameterConfig() 
const {
+  SensitiveParameterConfig config;
 
   auto sensitive_parameter_scope_str = 
getProperty(SensitiveParameterScope.name);
   if (!sensitive_parameter_scope_str) {
@@ -47,7 +56,7 @@ ParameterProviderConfig 
ParameterProvider::readParameterProviderConfig() const {
 }
 
 std::vector<gsl::not_null<std::unique_ptr<ParameterContext>>> 
ParameterProvider::createParameterContexts() {
-  auto config = readParameterProviderConfig();
+  auto config = readSensitiveParameterConfig();
 
   auto parameter_groups = buildParameterGroups();
   std::vector<gsl::not_null<std::unique_ptr<ParameterContext>>> result;
diff --git a/libminifi/src/core/flow/StructuredConfiguration.cpp 
b/libminifi/src/core/flow/StructuredConfiguration.cpp
index 5eb856c5f..7b706bb6a 100644
--- a/libminifi/src/core/flow/StructuredConfiguration.cpp
+++ b/libminifi/src/core/flow/StructuredConfiguration.cpp
@@ -250,11 +250,14 @@ void 
StructuredConfiguration::parseParameterProvidersNode(const Node& parameter_
     parameter_provider->setName(name);
     auto parameter_contexts = parameter_provider->createParameterContexts();
     for (auto& parameter_context : parameter_contexts) {
-      if (!parameter_contexts_.contains(parameter_context->getName())) {
+      auto it = parameter_contexts_.find(parameter_context->getName());
+      if (it == parameter_contexts_.end()) {
         parameter_contexts_.emplace(parameter_context->getName(), 
std::move(parameter_context));
-      } else if 
(parameter_contexts_.at(parameter_context->getName())->getParameterProvider() 
!= parameter_provider->getUUIDStr()) {
+      } else if (it->second->getParameterProvider() != 
parameter_provider->getUUIDStr()) {
         throw std::invalid_argument(fmt::format("Parameter provider '{}' 
cannot create parameter context '{}' because parameter context already exists "
           "with no parameter provider or generated by other parameter 
provider", parameter_provider->getName(), parameter_context->getName()));
+      } else if (parameter_provider->reloadValuesOnRestart()) {
+        it->second = std::move(parameter_context);
       }
     }
     
parameter_providers_.push_back(gsl::make_not_null(std::move(parameter_provider)));
diff --git a/libminifi/src/core/json/JsonFlowSerializer.cpp 
b/libminifi/src/core/json/JsonFlowSerializer.cpp
index 1f43ffbb2..0c0088dc3 100644
--- a/libminifi/src/core/json/JsonFlowSerializer.cpp
+++ b/libminifi/src/core/json/JsonFlowSerializer.cpp
@@ -40,7 +40,7 @@ rapidjson::Value& getMember(rapidjson::Value& node, const 
std::string& member_na
 }
 
 void JsonFlowSerializer::addProviderCreatedParameterContexts(rapidjson::Value& 
flow_definition_json, rapidjson::Document::AllocatorType& alloc, const 
core::flow::FlowSchema& schema,
-    const std::unordered_map<std::string, 
gsl::not_null<std::unique_ptr<ParameterContext>>>& parameter_contexts) const {
+    const std::unordered_map<std::string, 
gsl::not_null<std::unique_ptr<ParameterContext>>>& parameter_contexts) {
   std::vector<gsl::not_null<ParameterContext*>> provided_parameter_contexts;
   for (const auto& [parameter_context_name, parameter_context] : 
parameter_contexts) {
     if (!parameter_context->getParameterProvider().empty()) {
@@ -52,21 +52,11 @@ void 
JsonFlowSerializer::addProviderCreatedParameterContexts(rapidjson::Value& f
     return;
   }
 
-  std::unordered_set<std::string> parameter_context_names;
-  if (flow_definition_json.HasMember(schema.parameter_contexts[0])) {
-    auto parameter_contexts_node = getMember(flow_definition_json, 
schema.parameter_contexts[0]).GetArray();
-    for (auto& parameter_context : parameter_contexts_node) {
-      parameter_context_names.insert(getMember(parameter_context, 
schema.name[0]).GetString());
-    }
-  } else {
+  if (!flow_definition_json.HasMember(schema.parameter_contexts[0])) {
     
flow_definition_json.AddMember(rapidjson::Value(schema.parameter_contexts[0].c_str(),
 alloc), rapidjson::Value(rapidjson::kArrayType), alloc);
   }
 
   for (const auto& parameter_context : provided_parameter_contexts) {
-    if (parameter_context_names.contains(parameter_context->getName())) {
-      logger_->log_warn("Parameter context '{}' already exists in the flow 
definition, will not be updated!", parameter_context->getName());
-      continue;
-    }
     rapidjson::Value parameter_context_json(rapidjson::kObjectType);
     parameter_context_json.AddMember(rapidjson::Value(schema.identifier[0], 
alloc), rapidjson::Value(parameter_context->getUUIDStr(), alloc), alloc);
     parameter_context_json.AddMember(rapidjson::Value(schema.name[0], alloc), 
rapidjson::Value(parameter_context->getName(), alloc), alloc);
@@ -85,7 +75,15 @@ void 
JsonFlowSerializer::addProviderCreatedParameterContexts(rapidjson::Value& f
     parameter_context_json.AddMember(rapidjson::Value(schema.parameters[0], 
alloc), parameters_json, alloc);
 
     auto& parameter_contexts_node = getMember(flow_definition_json, 
schema.parameter_contexts[0]);
-    parameter_contexts_node.PushBack(parameter_context_json, alloc);
+    auto it = std::find_if(parameter_contexts_node.Begin(), 
parameter_contexts_node.End(), [&](rapidjson::Value& node) {
+      return getMember(node, schema.name[0]).GetString() == 
parameter_context->getName();
+    });
+
+    if (it != parameter_contexts_node.End()) {
+      *it = parameter_context_json;
+    } else {
+      parameter_contexts_node.PushBack(parameter_context_json, alloc);
+    }
   }
 }
 
diff --git a/libminifi/src/core/yaml/YamlFlowSerializer.cpp 
b/libminifi/src/core/yaml/YamlFlowSerializer.cpp
index c4a852716..eff5f49aa 100644
--- a/libminifi/src/core/yaml/YamlFlowSerializer.cpp
+++ b/libminifi/src/core/yaml/YamlFlowSerializer.cpp
@@ -24,7 +24,7 @@
 namespace org::apache::nifi::minifi::core::yaml {
 
 void YamlFlowSerializer::addProviderCreatedParameterContexts(YAML::Node 
flow_definition_yaml, const core::flow::FlowSchema& schema,
-    const std::unordered_map<std::string, 
gsl::not_null<std::unique_ptr<ParameterContext>>>& parameter_contexts) const {
+    const std::unordered_map<std::string, 
gsl::not_null<std::unique_ptr<ParameterContext>>>& parameter_contexts) {
   std::vector<gsl::not_null<ParameterContext*>> provided_parameter_contexts;
   for (const auto& [parameter_context_name, parameter_context] : 
parameter_contexts) {
     if (!parameter_context->getParameterProvider().empty()) {
@@ -36,23 +36,13 @@ void 
YamlFlowSerializer::addProviderCreatedParameterContexts(YAML::Node flow_def
     return;
   }
 
-  std::unordered_set<std::string> parameter_context_names;
   auto parameter_contexts_node = 
flow_definition_yaml[schema.parameter_contexts[0]];
 
-  if (parameter_contexts_node.IsDefined() && 
parameter_contexts_node.IsSequence()) {
-    for (const auto& parameter_context : parameter_contexts_node) {
-      
parameter_context_names.insert(parameter_context[schema.name[0]].as<std::string>());
-    }
-  } else {
+  if (!parameter_contexts_node.IsDefined() || 
!parameter_contexts_node.IsSequence()) {
     parameter_contexts_node = YAML::Node(YAML::NodeType::Sequence);
   }
 
   for (const auto& parameter_context : provided_parameter_contexts) {
-    if (parameter_context_names.contains(parameter_context->getName())) {
-      logger_->log_warn("Parameter context '{}' already exists in the flow 
definition, will not be updated!", parameter_context->getName());
-      continue;
-    }
-
     YAML::Node parameter_context_node;
     parameter_context_node[schema.identifier[0]] = 
std::string(parameter_context->getUUIDStr());
     parameter_context_node[schema.name[0]] = parameter_context->getName();
@@ -72,7 +62,19 @@ void 
YamlFlowSerializer::addProviderCreatedParameterContexts(YAML::Node flow_def
     }
 
     parameter_context_node[schema.parameters[0]] = parameters_node;
-    parameter_contexts_node.push_back(parameter_context_node);
+
+    int64_t index = -1;
+    for (int64_t i = 0; i < 
gsl::narrow<int64_t>(parameter_contexts_node.size()); ++i) {
+      if (parameter_contexts_node[i][schema.name[0]].as<std::string>() == 
parameter_context->getName()) {
+        index = i;
+        break;
+      }
+    }
+    if (index != -1) {
+      parameter_contexts_node[index] = parameter_context_node;
+    } else {
+      parameter_contexts_node.push_back(parameter_context_node);
+    }
   }
 }
 
diff --git a/libminifi/test/unit/JsonFlowSerializerTests.cpp 
b/libminifi/test/unit/JsonFlowSerializerTests.cpp
index 92fa3f76f..729a62a30 100644
--- a/libminifi/test/unit/JsonFlowSerializerTests.cpp
+++ b/libminifi/test/unit/JsonFlowSerializerTests.cpp
@@ -901,4 +901,93 @@ TEST_CASE("Parameter provider generated parameter context 
is not serialized if p
   }
 }
 
+TEST_CASE("Parameter provider generated parameter context is reserialized if 
Reload Values On Restart is set to true") {
+  ConfigurationTestController test_controller;
+  auto configuration_context = test_controller.getContext();
+  configuration_context.sensitive_values_encryptor = encryption_provider;
+  core::flow::AdaptiveConfiguration 
json_configuration_before{configuration_context};
+
+  const auto schema = core::flow::FlowSchema::getNiFiFlowJson();
+  static const std::string config_json_with_nifi_schema =
+      R"(
+{
+  "parameterProviders": [
+    {
+        "identifier": "d26ee5f5-0192-1000-0482-4e333725e089",
+        "name": "EnvironmentVariableParameterProvider",
+        "type": "EnvironmentVariableParameterProvider",
+        "properties": {
+          "Environment Variable Inclusion Strategy": "Comma-Separated",
+          "Include Environment Variables": "MINIFI_DATA,SECRET_MINIFI_DATA",
+          "Sensitive Parameter Scope": "selected",
+          "Sensitive Parameter List": "SECRET_MINIFI_DATA",
+          "Parameter Group Name": "environment-variable-parameter-context",
+          "Reload Values On Restart": "true"
+        }
+    }
+  ],
+  "parameterContexts": [
+    {
+        "identifier": "123ee5f5-0192-1000-0482-4e333725e345",
+        "name": "environment-variable-parameter-context",
+        "description": "my parameter context",
+        "parameters": [
+            {
+                "name": "SECRET_MINIFI_DATA",
+                "description": "",
+                "sensitive": true,
+                "provided": true,
+                "value": "old_secret_minifi_data_value"
+            },
+            {
+                "name": "MINIFI_DATA",
+                "description": "",
+                "sensitive": false,
+                "provided": true,
+                "value": "old_minifi_data_value"
+            }
+        ],
+        "parameterProvider": "d26ee5f5-0192-1000-0482-4e333725e089"
+    }
+  ],
+  "rootGroup": {
+    "name": "MiNiFi Flow",
+    "processors": [{
+      "name": "DummyProcessor",
+      "identifier": "aabb6d26-8a8d-4338-92c9-1b8c67ec18e0",
+      "type": "DummyProcessor",
+      "scheduling strategy": "TIMER_DRIVEN",
+      "scheduling period": "15 sec",
+      "properties": {
+        "Simple Property": "#{MINIFI_DATA}",
+        "Sensitive Property": "#{SECRET_MINIFI_DATA}"
+      }
+    }],
+    "parameterContextName": "environment-variable-parameter-context"
+  }
+})";
+
+  minifi::utils::Environment::setEnvironmentVariable("MINIFI_DATA", 
"minifi_data_value");
+  minifi::utils::Environment::setEnvironmentVariable("SECRET_MINIFI_DATA", 
"secret_minifi_data_value");
+  const auto process_group_before = 
json_configuration_before.getRootFromPayload(config_json_with_nifi_schema);
+  REQUIRE(process_group_before);
+
+  std::string reserialized_config = 
json_configuration_before.serialize(*process_group_before);
+  rapidjson::Document result_doc;
+  rapidjson::ParseResult res = result_doc.Parse(reserialized_config.data(), 
reserialized_config.size());
+  REQUIRE(res);
+  REQUIRE(result_doc.HasMember("parameterContexts"));
+  auto parameters = 
result_doc["parameterContexts"].GetArray()[0]["parameters"].GetArray();
+  REQUIRE(parameters.Size() == 2);
+  for (const auto& parameter : parameters) {
+    std::string name = parameter["name"].GetString();
+    std::string value = parameter["value"].GetString();
+    if (name == "MINIFI_DATA") {
+      CHECK(value == "minifi_data_value");
+    } else if (name == "SECRET_MINIFI_DATA") {
+      CHECK(minifi::utils::crypto::property_encryption::decrypt(value, 
encryption_provider) == "secret_minifi_data_value");
+    }
+  }
+}
+
 }  // namespace org::apache::nifi::minifi::test
diff --git a/libminifi/test/unit/YamlFlowSerializerTests.cpp 
b/libminifi/test/unit/YamlFlowSerializerTests.cpp
index e79c4be39..78e07eac1 100644
--- a/libminifi/test/unit/YamlFlowSerializerTests.cpp
+++ b/libminifi/test/unit/YamlFlowSerializerTests.cpp
@@ -489,4 +489,77 @@ Parameter Context Name: 
environment-variable-parameter-context
   }
 }
 
+TEST_CASE("Parameter provider generated parameter context is reserialized if 
Reload Values On Restart is set to true") {
+  ConfigurationTestController test_controller;
+  auto configuration_context = test_controller.getContext();
+  configuration_context.sensitive_values_encryptor = encryption_provider;
+  core::flow::AdaptiveConfiguration 
yaml_configuration_before{configuration_context};
+
+  const auto schema = core::flow::FlowSchema::getDefault();
+  static const std::string config_yaml =
+      R"(
+Flow Controller:
+  name: root
+  comment: ""
+Parameter Providers:
+  - id: d26ee5f5-0192-1000-0482-4e333725e089
+    name: EnvironmentVariableParameterProvider
+    type: EnvironmentVariableParameterProvider
+    Properties:
+      Environment Variable Inclusion Strategy: Comma-Separated
+      Include Environment Variables: MINIFI_DATA,SECRET_MINIFI_DATA
+      Sensitive Parameter Scope: selected
+      Sensitive Parameter List: SECRET_MINIFI_DATA
+      Parameter Group Name: environment-variable-parameter-context
+      Reload Values On Restart: true
+Parameter Contexts:
+  - id: 123ee5f5-0192-1000-0482-4e333725e345
+    name: environment-variable-parameter-context
+    description: my parameter context
+    Parameters:
+      - name: SECRET_MINIFI_DATA
+        description: ''
+        sensitive: true
+        provided: true
+        value: old_secret_minifi_data_value
+      - name: MINIFI_DATA
+        description: ''
+        sensitive: false
+        provided: true
+        value: old_minifi_data_value
+    Parameter Provider: d26ee5f5-0192-1000-0482-4e333725e089
+Processors:
+  - name: DummyProcessor
+    id: aabb6d26-8a8d-4338-92c9-1b8c67ec18e0
+    type: DummyProcessor
+    scheduling strategy: TIMER_DRIVEN
+    scheduling period: "15 sec"
+    Properties:
+      Simple Property: "#{MINIFI_DATA}"
+      Sensitive Property: "#{SECRET_MINIFI_DATA}"
+Parameter Context Name: environment-variable-parameter-context
+)";
+
+  minifi::utils::Environment::setEnvironmentVariable("MINIFI_DATA", 
"minifi_data_value");
+  minifi::utils::Environment::setEnvironmentVariable("SECRET_MINIFI_DATA", 
"secret_minifi_data_value");
+  const auto process_group_before = 
yaml_configuration_before.getRootFromPayload(std::string{config_yaml});
+  REQUIRE(process_group_before);
+
+  std::string reserialized_config = 
yaml_configuration_before.serialize(*process_group_before);
+  YAML::Node result_yaml_node = YAML::Load(std::string{reserialized_config});
+
+  REQUIRE(result_yaml_node["Parameter Contexts"].IsDefined());
+  auto parameters = result_yaml_node["Parameter Contexts"][0]["Parameters"];
+  REQUIRE(parameters.size() == 2);
+  for (const auto& parameter : parameters) {
+    auto name = parameter["name"].as<std::string>();
+    auto value = parameter["value"].as<std::string>();
+    if (name == "MINIFI_DATA") {
+      CHECK(value == "minifi_data_value");
+    } else if (name == "SECRET_MINIFI_DATA") {
+      CHECK(minifi::utils::crypto::property_encryption::decrypt(value, 
encryption_provider) == "secret_minifi_data_value");
+    }
+  }
+}
+
 }  // namespace org::apache::nifi::minifi::test

Reply via email to