Report: Add TriggerIds property

This change is adding TriggerIds property for Report interface. It is an
array of strings, each representing id of trigger which may update given
report Readings property, due to UpdateReport action. This properly is
read-only, but it can be changed in the runtime, when:
- New Trigger is made using AddTrigger dbus method, when ReportId
  argument contains id of given report.
- Trigger is deleted from dbus, and its ReportNames property included id
  of given report.
- ReportNames property of any trigger is updated to include (or not) id
  of given report.

When this property is modified by service, signal will be emitted on
dbus for property change.

When there is existing trigger with id of non-existing report in its
ReportNames property, its id will be added to TriggerIds property of
such report, the moment it is created by user.

Testing done:
- new UTs were made, all UTs are passing.
- manual testing on dbus interface was successful.

Signed-off-by: Szymon Dompke <szymon.dompke@intel.com>
Change-Id: I1c4c94ce751ddaee001e3cadde3ea60aa8e1c224
diff --git a/src/interfaces/report.hpp b/src/interfaces/report.hpp
index 4b3bd9e..122afdf 100644
--- a/src/interfaces/report.hpp
+++ b/src/interfaces/report.hpp
@@ -1,5 +1,7 @@
 #pragma once
 
+#include "types/report_types.hpp"
+
 #include <string>
 
 namespace interfaces
@@ -13,5 +15,7 @@
     virtual std::string getId() const = 0;
     virtual std::string getPath() const = 0;
     virtual void updateReadings() = 0;
+    virtual void updateTriggerIds(const std::string& triggerId,
+                                  TriggerIdUpdate updateType) = 0;
 };
 } // namespace interfaces
diff --git a/src/interfaces/report_factory.hpp b/src/interfaces/report_factory.hpp
index 6a255a4..f5a1c5b 100644
--- a/src/interfaces/report_factory.hpp
+++ b/src/interfaces/report_factory.hpp
@@ -26,15 +26,14 @@
         convertMetricParams(boost::asio::yield_context& yield,
                             const ReadingParameters& metricParams) const = 0;
 
-    virtual std::unique_ptr<interfaces::Report>
-        make(const std::string& id, const std::string& name,
-             const ReportingType reportingType,
-             const std::vector<ReportAction>& reportActions,
-             Milliseconds period, uint64_t appendLimit,
-             const ReportUpdates reportUpdates, ReportManager& reportManager,
-             JsonStorage& reportStorage,
-             std::vector<LabeledMetricParameters> labeledMetricParams,
-             bool enabled) const = 0;
+    virtual std::unique_ptr<interfaces::Report> make(
+        const std::string& id, const std::string& name,
+        const ReportingType reportingType,
+        const std::vector<ReportAction>& reportActions, Milliseconds period,
+        uint64_t appendLimit, const ReportUpdates reportUpdates,
+        ReportManager& reportManager, JsonStorage& reportStorage,
+        std::vector<LabeledMetricParameters> labeledMetricParams, bool enabled,
+        const std::vector<std::string>& triggerIds) const = 0;
 };
 
 } // namespace interfaces
diff --git a/src/interfaces/report_manager.hpp b/src/interfaces/report_manager.hpp
index 901c446..a390f41 100644
--- a/src/interfaces/report_manager.hpp
+++ b/src/interfaces/report_manager.hpp
@@ -1,6 +1,7 @@
 #pragma once
 
 #include "interfaces/report.hpp"
+#include "types/report_types.hpp"
 
 namespace interfaces
 {
@@ -12,6 +13,9 @@
 
     virtual void removeReport(const interfaces::Report* report) = 0;
     virtual void updateReport(const std::string& id) = 0;
+    virtual void updateTriggerIds(const std::string& reportId,
+                                  const std::string& triggerId,
+                                  TriggerIdUpdate updateType) = 0;
 };
 
 } // namespace interfaces
diff --git a/src/interfaces/trigger.hpp b/src/interfaces/trigger.hpp
index 4ec5070..7ad47ae 100644
--- a/src/interfaces/trigger.hpp
+++ b/src/interfaces/trigger.hpp
@@ -1,6 +1,7 @@
 #pragma once
 
 #include <string>
+#include <vector>
 
 namespace interfaces
 {
@@ -12,6 +13,7 @@
 
     virtual std::string getId() const = 0;
     virtual std::string getPath() const = 0;
+    virtual const std::vector<std::string>& getReportIds() const = 0;
 };
 
 } // namespace interfaces
diff --git a/src/interfaces/trigger_manager.hpp b/src/interfaces/trigger_manager.hpp
index 878fd57..28e11f3 100644
--- a/src/interfaces/trigger_manager.hpp
+++ b/src/interfaces/trigger_manager.hpp
@@ -11,6 +11,9 @@
     virtual ~TriggerManager() = default;
 
     virtual void removeTrigger(const Trigger* trigger) = 0;
+
+    virtual std::vector<std::string>
+        getTriggerIdsForReport(const std::string& reportId) const = 0;
 };
 
 } // namespace interfaces
diff --git a/src/report.cpp b/src/report.cpp
index 8acf182..6439d41 100644
--- a/src/report.cpp
+++ b/src/report.cpp
@@ -21,7 +21,8 @@
                interfaces::ReportManager& reportManager,
                interfaces::JsonStorage& reportStorageIn,
                std::vector<std::shared_ptr<interfaces::Metric>> metricsIn,
-               const bool enabledIn, std::unique_ptr<interfaces::Clock> clock) :
+               const bool enabledIn, std::unique_ptr<interfaces::Clock> clock,
+               const std::vector<std::string>& triggerIdsIn) :
     id(reportId),
     name(reportName), reportingType(reportingTypeIn), interval(intervalIn),
     reportActions(std::move(reportActionsIn)),
@@ -30,6 +31,7 @@
     reportUpdates(reportUpdatesIn),
     readingsBuffer(deduceBufferSize(reportUpdates, reportingType)),
     objServer(objServer), metrics(std::move(metricsIn)), timer(ioc),
+    triggerIds(triggerIdsIn.begin(), triggerIdsIn.end()),
     reportStorage(reportStorageIn), enabled(enabledIn), clock(std::move(clock))
 {
     readingParameters =
@@ -257,6 +259,12 @@
             return 1;
         },
         [this](const auto&) { return utils::enumToString(reportUpdates); });
+    dbusIface->register_property_r(
+        "TriggerIds", std::vector<std::string>{},
+        sdbusplus::vtable::property_::emits_change, [this](const auto&) {
+            return std::vector<std::string>(triggerIds.begin(),
+                                            triggerIds.end());
+        });
     dbusIface->register_method("Update", [this] {
         if (reportingType == ReportingType::onRequest)
         {
@@ -362,8 +370,28 @@
 
     return true;
 }
+
 interfaces::JsonStorage::FilePath Report::fileName() const
 {
     return interfaces::JsonStorage::FilePath{
         std::to_string(std::hash<std::string>{}(id))};
 }
+
+void Report::updateTriggerIds(const std::string& triggerId,
+                              TriggerIdUpdate updateType)
+{
+    if (updateType == TriggerIdUpdate::Add)
+    {
+        if (triggerIds.insert(triggerId).second)
+        {
+            reportIface->signal_property("TriggerIds");
+        }
+    }
+    else if (updateType == TriggerIdUpdate::Remove)
+    {
+        if (triggerIds.erase(triggerId) > 0)
+        {
+            reportIface->signal_property("TriggerIds");
+        }
+    }
+}
diff --git a/src/report.hpp b/src/report.hpp
index 98097ae..3e649fd 100644
--- a/src/report.hpp
+++ b/src/report.hpp
@@ -17,6 +17,7 @@
 
 #include <chrono>
 #include <memory>
+#include <unordered_set>
 
 class Report : public interfaces::Report
 {
@@ -30,7 +31,8 @@
            interfaces::ReportManager& reportManager,
            interfaces::JsonStorage& reportStorage,
            std::vector<std::shared_ptr<interfaces::Metric>> metrics,
-           const bool enabled, std::unique_ptr<interfaces::Clock> clock);
+           const bool enabled, std::unique_ptr<interfaces::Clock> clock,
+           const std::vector<std::string>& triggerIds);
 
     Report(const Report&) = delete;
     Report(Report&&) = delete;
@@ -48,6 +50,8 @@
     }
 
     void updateReadings() override;
+    void updateTriggerIds(const std::string& triggerId,
+                          TriggerIdUpdate updateType) override;
     bool storeConfiguration() const;
 
   private:
@@ -81,6 +85,7 @@
     std::unique_ptr<sdbusplus::asio::dbus_interface> deleteIface;
     std::vector<std::shared_ptr<interfaces::Metric>> metrics;
     boost::asio::steady_timer timer;
+    std::unordered_set<std::string> triggerIds;
 
     interfaces::JsonStorage& reportStorage;
     bool enabled;
diff --git a/src/report_factory.cpp b/src/report_factory.cpp
index df71fa0..df197a4 100644
--- a/src/report_factory.cpp
+++ b/src/report_factory.cpp
@@ -23,8 +23,8 @@
     uint64_t appendLimit, const ReportUpdates reportUpdates,
     interfaces::ReportManager& reportManager,
     interfaces::JsonStorage& reportStorage,
-    std::vector<LabeledMetricParameters> labeledMetricParams,
-    bool enabled) const
+    std::vector<LabeledMetricParameters> labeledMetricParams, bool enabled,
+    const std::vector<std::string>& triggerIds) const
 {
     std::vector<std::shared_ptr<interfaces::Metric>> metrics = utils::transform(
         labeledMetricParams,
@@ -40,10 +40,11 @@
                 std::make_unique<Clock>());
         });
 
-    return std::make_unique<Report>(
-        bus->get_io_context(), objServer, id, name, reportingType,
-        reportActions, period, appendLimit, reportUpdates, reportManager,
-        reportStorage, std::move(metrics), enabled, std::make_unique<Clock>());
+    return std::make_unique<Report>(bus->get_io_context(), objServer, id, name,
+                                    reportingType, reportActions, period,
+                                    appendLimit, reportUpdates, reportManager,
+                                    reportStorage, std::move(metrics), enabled,
+                                    std::make_unique<Clock>(), triggerIds);
 }
 
 Sensors ReportFactory::getSensors(
diff --git a/src/report_factory.hpp b/src/report_factory.hpp
index 14f9f39..e841be1 100644
--- a/src/report_factory.hpp
+++ b/src/report_factory.hpp
@@ -20,16 +20,15 @@
         boost::asio::yield_context& yield,
         const ReadingParameters& metricParams) const override;
 
-    std::unique_ptr<interfaces::Report>
-        make(const std::string& reportId, const std::string& name,
-             const ReportingType reportingType,
-             const std::vector<ReportAction>& reportActions,
-             Milliseconds period, uint64_t appendLimitIn,
-             const ReportUpdates reportUpdatesIn,
-             interfaces::ReportManager& reportManager,
-             interfaces::JsonStorage& reportStorage,
-             std::vector<LabeledMetricParameters> labeledMetricParams,
-             bool enabled) const override;
+    std::unique_ptr<interfaces::Report> make(
+        const std::string& reportId, const std::string& name,
+        const ReportingType reportingType,
+        const std::vector<ReportAction>& reportActions, Milliseconds period,
+        uint64_t appendLimitIn, const ReportUpdates reportUpdatesIn,
+        interfaces::ReportManager& reportManager,
+        interfaces::JsonStorage& reportStorage,
+        std::vector<LabeledMetricParameters> labeledMetricParams, bool enabled,
+        const std::vector<std::string>& triggerIds) const override;
 
   private:
     Sensors getSensors(const std::vector<LabeledSensorInfo>& sensorPaths) const;
diff --git a/src/report_manager.cpp b/src/report_manager.cpp
index f5dc105..9b7b9ef 100644
--- a/src/report_manager.cpp
+++ b/src/report_manager.cpp
@@ -32,9 +32,11 @@
 ReportManager::ReportManager(
     std::unique_ptr<interfaces::ReportFactory> reportFactoryIn,
     std::unique_ptr<interfaces::JsonStorage> reportStorageIn,
-    const std::shared_ptr<sdbusplus::asio::object_server>& objServerIn) :
+    const std::shared_ptr<sdbusplus::asio::object_server>& objServerIn,
+    std::unique_ptr<interfaces::TriggerManager>& triggerManagerIn) :
     reportFactory(std::move(reportFactoryIn)),
-    reportStorage(std::move(reportStorageIn)), objServer(objServerIn)
+    reportStorage(std::move(reportStorageIn)), objServer(objServerIn),
+    triggerManager(triggerManagerIn)
 {
     reports.reserve(maxReports);
 
@@ -223,9 +225,16 @@
     verifyAddReport(id, name, reportingType, interval, reportUpdates,
                     appendLimit, labeledMetricParams);
 
-    reports.emplace_back(reportFactory->make(
-        id, name, reportingType, reportActions, interval, appendLimit,
-        reportUpdates, *this, *reportStorage, labeledMetricParams, enabled));
+    std::vector<std::string> triggerIds;
+    if (triggerManager)
+    {
+        triggerIds = triggerManager->getTriggerIdsForReport(id);
+    }
+
+    reports.emplace_back(
+        reportFactory->make(id, name, reportingType, reportActions, interval,
+                            appendLimit, reportUpdates, *this, *reportStorage,
+                            labeledMetricParams, enabled, triggerIds));
     return *reports.back();
 }
 
@@ -290,3 +299,17 @@
         }
     }
 }
+
+void ReportManager::updateTriggerIds(const std::string& reportId,
+                                     const std::string& triggerId,
+                                     TriggerIdUpdate updateType)
+{
+    if (auto res = std::find_if(reports.begin(), reports.end(),
+                                [&reportId](const auto& report) {
+                                    return report->getId() == reportId;
+                                });
+        res != reports.end())
+    {
+        (*res)->updateTriggerIds(triggerId, updateType);
+    }
+}
diff --git a/src/report_manager.hpp b/src/report_manager.hpp
index 93b2986..85fbfa9 100644
--- a/src/report_manager.hpp
+++ b/src/report_manager.hpp
@@ -4,6 +4,7 @@
 #include "interfaces/report.hpp"
 #include "interfaces/report_factory.hpp"
 #include "interfaces/report_manager.hpp"
+#include "interfaces/trigger_manager.hpp"
 #include "report.hpp"
 
 #include <systemd/sd-bus-protocol.h>
@@ -21,7 +22,8 @@
     ReportManager(
         std::unique_ptr<interfaces::ReportFactory> reportFactory,
         std::unique_ptr<interfaces::JsonStorage> reportStorage,
-        const std::shared_ptr<sdbusplus::asio::object_server>& objServer);
+        const std::shared_ptr<sdbusplus::asio::object_server>& objServer,
+        std::unique_ptr<interfaces::TriggerManager>& triggerManager);
     ~ReportManager() = default;
 
     ReportManager(const ReportManager&) = delete;
@@ -31,6 +33,9 @@
 
     void removeReport(const interfaces::Report* report) override;
     void updateReport(const std::string& id) override;
+    void updateTriggerIds(const std::string& reportId,
+                          const std::string& triggerId,
+                          TriggerIdUpdate updateType) override;
 
   private:
     std::unique_ptr<interfaces::ReportFactory> reportFactory;
@@ -38,6 +43,7 @@
     std::shared_ptr<sdbusplus::asio::object_server> objServer;
     std::unique_ptr<sdbusplus::asio::dbus_interface> reportManagerIface;
     std::vector<std::unique_ptr<interfaces::Report>> reports;
+    std::unique_ptr<interfaces::TriggerManager>& triggerManager;
 
     void verifyAddReport(
         const std::string& reportId, const std::string& reportName,
diff --git a/src/telemetry.hpp b/src/telemetry.hpp
index 633c4b0..c3f8f17 100644
--- a/src/telemetry.hpp
+++ b/src/telemetry.hpp
@@ -22,18 +22,19 @@
             std::make_unique<PersistentJsonStorage>(
                 interfaces::JsonStorage::DirectoryPath(
                     "/var/lib/telemetry/Reports")),
-            objServer),
-        triggerManager(std::make_unique<TriggerFactory>(
-                           bus, objServer, sensorCache, reportManager),
-                       std::make_unique<PersistentJsonStorage>(
-                           interfaces::JsonStorage::DirectoryPath(
-                               "/var/lib/telemetry/Triggers")),
-                       objServer)
+            objServer, triggerManager),
+        triggerManager(std::make_unique<TriggerManager>(
+            std::make_unique<TriggerFactory>(bus, objServer, sensorCache,
+                                             reportManager),
+            std::make_unique<PersistentJsonStorage>(
+                interfaces::JsonStorage::DirectoryPath(
+                    "/var/lib/telemetry/Triggers")),
+            objServer))
     {}
 
   private:
     std::shared_ptr<sdbusplus::asio::object_server> objServer;
     mutable SensorCache sensorCache;
     ReportManager reportManager;
-    TriggerManager triggerManager;
+    std::unique_ptr<interfaces::TriggerManager> triggerManager;
 };
diff --git a/src/trigger.cpp b/src/trigger.cpp
index db988ff..34609b3 100644
--- a/src/trigger.cpp
+++ b/src/trigger.cpp
@@ -17,13 +17,15 @@
     std::vector<std::shared_ptr<interfaces::Threshold>>&& thresholdsIn,
     interfaces::TriggerManager& triggerManager,
     interfaces::JsonStorage& triggerStorageIn,
-    const interfaces::TriggerFactory& triggerFactory, Sensors sensorsIn) :
+    const interfaces::TriggerFactory& triggerFactory, Sensors sensorsIn,
+    interfaces::ReportManager& reportManagerIn) :
     id(idIn),
     name(nameIn), triggerActions(std::move(triggerActionsIn)),
     path(triggerDir + id), reportIds(std::move(reportIdsIn)),
     thresholds(std::move(thresholdsIn)),
     fileName(std::to_string(std::hash<std::string>{}(id))),
-    triggerStorage(triggerStorageIn), sensors(std::move(sensorsIn))
+    triggerStorage(triggerStorageIn), sensors(std::move(sensorsIn)),
+    reportManager(reportManagerIn)
 {
     deleteIface = objServer->add_unique_interface(
         path, deleteIfaceName, [this, &ioc, &triggerManager](auto& dbusIface) {
@@ -32,6 +34,11 @@
                 {
                     triggerStorage.remove(fileName);
                 }
+                for (const auto& reportId : *reportIds)
+                {
+                    reportManager.updateTriggerIds(reportId, id,
+                                                   TriggerIdUpdate::Remove);
+                }
                 boost::asio::post(ioc, [this, &triggerManager] {
                     triggerManager.removeTrigger(this);
                 });
@@ -106,6 +113,8 @@
                 "ReportNames", std::vector<std::string>{},
                 sdbusplus::vtable::property_::emits_change,
                 [this](auto newVal, auto& oldVal) {
+                    TriggerManager::verifyReportIds(newVal);
+                    updateTriggerIdsInReports(newVal);
                     reportIds->clear();
                     std::copy(newVal.begin(), newVal.end(),
                               std::back_inserter(*reportIds));
@@ -145,6 +154,11 @@
     {
         threshold->initialize();
     }
+
+    for (const auto& reportId : *reportIds)
+    {
+        reportManager.updateTriggerIds(reportId, id, TriggerIdUpdate::Add);
+    }
 }
 
 bool Trigger::storeConfiguration() const
@@ -186,3 +200,26 @@
     }
     return true;
 }
+
+void Trigger::updateTriggerIdsInReports(
+    const std::vector<std::string>& newReportIds)
+{
+    std::vector<std::string> toBeRemoved, toBeAdded;
+    size_t maxSize = std::max(reportIds->size(), newReportIds.size());
+    toBeRemoved.reserve(maxSize);
+    toBeAdded.reserve(maxSize);
+    std::set_difference(reportIds->begin(), reportIds->end(),
+                        newReportIds.begin(), newReportIds.end(),
+                        std::back_inserter(toBeRemoved));
+    std::set_difference(newReportIds.begin(), newReportIds.end(),
+                        reportIds->begin(), reportIds->end(),
+                        std::back_inserter(toBeAdded));
+    for (auto& reportId : toBeRemoved)
+    {
+        reportManager.updateTriggerIds(reportId, id, TriggerIdUpdate::Remove);
+    }
+    for (auto& reportId : toBeAdded)
+    {
+        reportManager.updateTriggerIds(reportId, id, TriggerIdUpdate::Add);
+    }
+}
diff --git a/src/trigger.hpp b/src/trigger.hpp
index a9348bd..67c6a7f 100644
--- a/src/trigger.hpp
+++ b/src/trigger.hpp
@@ -1,6 +1,7 @@
 #pragma once
 
 #include "interfaces/json_storage.hpp"
+#include "interfaces/report_manager.hpp"
 #include "interfaces/threshold.hpp"
 #include "interfaces/trigger.hpp"
 #include "interfaces/trigger_factory.hpp"
@@ -23,8 +24,8 @@
             std::vector<std::shared_ptr<interfaces::Threshold>>&& thresholds,
             interfaces::TriggerManager& triggerManager,
             interfaces::JsonStorage& triggerStorage,
-            const interfaces::TriggerFactory& triggerFactory,
-            Sensors sensorsIn);
+            const interfaces::TriggerFactory& triggerFactory, Sensors sensorsIn,
+            interfaces::ReportManager& reportManager);
 
     Trigger(const Trigger&) = delete;
     Trigger(Trigger&&) = delete;
@@ -43,6 +44,11 @@
 
     bool storeConfiguration() const;
 
+    const std::vector<std::string>& getReportIds() const override
+    {
+        return *reportIds;
+    }
+
   private:
     std::string id;
     std::string name;
@@ -57,6 +63,10 @@
     interfaces::JsonStorage::FilePath fileName;
     interfaces::JsonStorage& triggerStorage;
     Sensors sensors;
+    interfaces::ReportManager& reportManager;
+
+    void
+        updateTriggerIdsInReports(const std::vector<std::string>& newReportIds);
 
   public:
     static constexpr const char* triggerIfaceName =
diff --git a/src/trigger_factory.cpp b/src/trigger_factory.cpp
index c8b464e..04928df 100644
--- a/src/trigger_factory.cpp
+++ b/src/trigger_factory.cpp
@@ -227,7 +227,8 @@
 
     return std::make_unique<Trigger>(
         bus->get_io_context(), objServer, id, name, triggerActions, reportIds,
-        std::move(thresholds), triggerManager, triggerStorage, *this, sensors);
+        std::move(thresholds), triggerManager, triggerStorage, *this, sensors,
+        reportManager);
 }
 
 Sensors TriggerFactory::getSensors(
diff --git a/src/trigger_manager.cpp b/src/trigger_manager.cpp
index c0b20d7..d581f71 100644
--- a/src/trigger_manager.cpp
+++ b/src/trigger_manager.cpp
@@ -8,6 +8,8 @@
 
 #include <phosphor-logging/log.hpp>
 
+#include <unordered_set>
+
 TriggerManager::TriggerManager(
     std::unique_ptr<interfaces::TriggerFactory> triggerFactoryIn,
     std::unique_ptr<interfaces::JsonStorage> triggerStorageIn,
@@ -51,8 +53,21 @@
         triggers.end());
 }
 
-void TriggerManager::verifyAddTrigger(const std::string& triggerId,
-                                      const std::string& triggerName) const
+void TriggerManager::verifyReportIds(
+    const std::vector<std::string>& newReportIds)
+{
+    if (std::unordered_set(newReportIds.begin(), newReportIds.end()).size() !=
+        newReportIds.size())
+    {
+        throw sdbusplus::exception::SdBusError(
+            static_cast<int>(std::errc::invalid_argument),
+            "Duplicate element in ReportIds");
+    }
+}
+
+void TriggerManager::verifyAddTrigger(
+    const std::string& triggerId, const std::string& triggerName,
+    const std::vector<std::string>& newReportIds) const
 {
     if (triggers.size() >= maxTriggers)
     {
@@ -71,6 +86,8 @@
                 static_cast<int>(std::errc::file_exists), "Duplicate trigger");
         }
     }
+
+    verifyReportIds(newReportIds);
 }
 
 interfaces::Trigger& TriggerManager::addTrigger(
@@ -87,7 +104,7 @@
         utils::generateId(triggerIdIn, triggerNameIn, triggerNameDefault,
                           existingTriggerIds, maxTriggerIdLength);
 
-    verifyAddTrigger(id, name);
+    verifyAddTrigger(id, name, reportIds);
 
     triggers.emplace_back(triggerFactory->make(
         id, name, triggerActions, reportIds, *this, *triggerStorage,
@@ -157,3 +174,19 @@
         }
     }
 }
+
+std::vector<std::string>
+    TriggerManager::getTriggerIdsForReport(const std::string& reportId) const
+{
+    std::vector<std::string> result;
+    for (const auto& trigger : triggers)
+    {
+        const auto& reportIds = trigger->getReportIds();
+        if (std::find(reportIds.begin(), reportIds.end(), reportId) !=
+            reportIds.end())
+        {
+            result.emplace_back(trigger->getId());
+        }
+    }
+    return result;
+}
diff --git a/src/trigger_manager.hpp b/src/trigger_manager.hpp
index 72b6274..2c76c3a 100644
--- a/src/trigger_manager.hpp
+++ b/src/trigger_manager.hpp
@@ -25,6 +25,11 @@
 
     void removeTrigger(const interfaces::Trigger* trigger) override;
 
+    static void verifyReportIds(const std::vector<std::string>& newReportIds);
+
+    std::vector<std::string>
+        getTriggerIdsForReport(const std::string& reportId) const override;
+
   private:
     std::unique_ptr<interfaces::TriggerFactory> triggerFactory;
     std::unique_ptr<interfaces::JsonStorage> triggerStorage;
@@ -32,7 +37,8 @@
     std::vector<std::unique_ptr<interfaces::Trigger>> triggers;
 
     void verifyAddTrigger(const std::string& triggerId,
-                          const std::string& triggerName) const;
+                          const std::string& triggerName,
+                          const std::vector<std::string>& newReportIds) const;
 
     interfaces::Trigger&
         addTrigger(const std::string& triggerId, const std::string& triggerName,
diff --git a/src/types/report_types.hpp b/src/types/report_types.hpp
index c0f7b39..42f1ab0 100644
--- a/src/types/report_types.hpp
+++ b/src/types/report_types.hpp
@@ -36,3 +36,9 @@
 
 ReadingParameters
     toReadingParameters(const std::vector<LabeledMetricParameters>& labeled);
+
+enum class TriggerIdUpdate
+{
+    Add,
+    Remove
+};
diff --git a/tests/src/mocks/report_factory_mock.hpp b/tests/src/mocks/report_factory_mock.hpp
index c2e4dd2..cf9047f 100644
--- a/tests/src/mocks/report_factory_mock.hpp
+++ b/tests/src/mocks/report_factory_mock.hpp
@@ -37,7 +37,7 @@
                 WithArgs<1>(Invoke(&ReportFactoryMock::convertToLabeled)));
 
         ON_CALL(*this,
-                make(A<const std::string&>(), _, _, _, _, _, _, _, _, _, _))
+                make(A<const std::string&>(), _, _, _, _, _, _, _, _, _, _, _))
             .WillByDefault(WithArgs<0>(Invoke([](const std::string& id) {
                 return std::make_unique<NiceMock<ReportMock>>(id);
             })));
@@ -52,7 +52,7 @@
                  const std::vector<ReportAction>&, Milliseconds, uint64_t,
                  const ReportUpdates, interfaces::ReportManager&,
                  interfaces::JsonStorage&, std::vector<LabeledMetricParameters>,
-                 bool),
+                 bool, const std::vector<std::string>&),
                 (const, override));
 
     auto& expectMake(
@@ -60,6 +60,7 @@
         const testing::Matcher<interfaces::ReportManager&>& rm,
         const testing::Matcher<interfaces::JsonStorage&>& js)
     {
+        using testing::_;
         if (paramsRef)
         {
             const ReportParams& params = *paramsRef;
@@ -68,12 +69,12 @@
                             params.reportingType(), params.reportActions(),
                             params.interval(), params.appendLimit(),
                             params.reportUpdates(), rm, js,
-                            params.metricParameters(), params.enabled()));
+                            params.metricParameters(), params.enabled(), _));
         }
         else
         {
-            using testing::_;
-            return EXPECT_CALL(*this, make(_, _, _, _, _, _, _, rm, js, _, _));
+            return EXPECT_CALL(*this,
+                               make(_, _, _, _, _, _, _, rm, js, _, _, _));
         }
     }
 };
diff --git a/tests/src/mocks/report_manager_mock.hpp b/tests/src/mocks/report_manager_mock.hpp
index df79e12..25f40a0 100644
--- a/tests/src/mocks/report_manager_mock.hpp
+++ b/tests/src/mocks/report_manager_mock.hpp
@@ -9,4 +9,8 @@
   public:
     MOCK_METHOD(void, removeReport, (const interfaces::Report*), (override));
     MOCK_METHOD(void, updateReport, (const std::string& name), (override));
+    MOCK_METHOD(void, updateTriggerIds,
+                (const std::string& reportId, const std::string& triggerId,
+                 TriggerIdUpdate updateType),
+                (override));
 };
diff --git a/tests/src/mocks/report_mock.hpp b/tests/src/mocks/report_mock.hpp
index 758290c..6ececfc 100644
--- a/tests/src/mocks/report_mock.hpp
+++ b/tests/src/mocks/report_mock.hpp
@@ -24,5 +24,9 @@
     MOCK_METHOD(std::string, getId, (), (override, const));
     MOCK_METHOD(std::string, getPath, (), (override, const));
     MOCK_METHOD(void, updateReadings, (), (override));
+    MOCK_METHOD(void, updateTriggerIds,
+                (const std::string& triggerId, TriggerIdUpdate updateType),
+                (override));
+
     MOCK_METHOD(void, Die, ());
 };
diff --git a/tests/src/mocks/trigger_manager_mock.hpp b/tests/src/mocks/trigger_manager_mock.hpp
index 9377d2a..f9f898d 100644
--- a/tests/src/mocks/trigger_manager_mock.hpp
+++ b/tests/src/mocks/trigger_manager_mock.hpp
@@ -9,4 +9,6 @@
   public:
     MOCK_METHOD(void, removeTrigger, (const interfaces::Trigger* trigger),
                 (override));
+    MOCK_METHOD(std::vector<std::string>, getTriggerIdsForReport,
+                (const std::string& reportId), (const, override));
 };
diff --git a/tests/src/mocks/trigger_mock.hpp b/tests/src/mocks/trigger_mock.hpp
index cd0e5f4..bb38257 100644
--- a/tests/src/mocks/trigger_mock.hpp
+++ b/tests/src/mocks/trigger_mock.hpp
@@ -23,5 +23,7 @@
 
     MOCK_METHOD(std::string, getId, (), (const, override));
     MOCK_METHOD(std::string, getPath, (), (const, override));
+    MOCK_METHOD(const std::vector<std::string>&, getReportIds, (),
+                (const, override));
     MOCK_METHOD(void, Die, ());
 };
diff --git a/tests/src/params/report_params.hpp b/tests/src/params/report_params.hpp
index 19ea519..f6e547e 100644
--- a/tests/src/params/report_params.hpp
+++ b/tests/src/params/report_params.hpp
@@ -108,6 +108,17 @@
         return metricParametersProperty;
     }
 
+    ReportParams& triggerIds(std::vector<std::string> val)
+    {
+        triggerIdsProperty = std::move(val);
+        return *this;
+    }
+
+    std::vector<std::string> triggerIds() const
+    {
+        return triggerIdsProperty;
+    }
+
   private:
     std::string reportIdProperty = "TestId";
     std::string reportNameProperty = "TestReport";
@@ -133,5 +144,6 @@
              "MetricId2",
              CollectionTimeScope::point,
              CollectionDuration(Milliseconds(0u))}}};
+    std::vector<std::string> triggerIdsProperty{};
     bool enabledProperty = true;
 };
diff --git a/tests/src/params/trigger_params.hpp b/tests/src/params/trigger_params.hpp
index ea7f7dc..b17ea86 100644
--- a/tests/src/params/trigger_params.hpp
+++ b/tests/src/params/trigger_params.hpp
@@ -54,6 +54,12 @@
         return reportIdsProperty;
     }
 
+    TriggerParams& reportIds(std::vector<std::string> val)
+    {
+        reportIdsProperty = std::move(val);
+        return *this;
+    }
+
     TriggerParams& thresholdParams(LabeledTriggerThresholdParams val)
     {
         labeledThresholdsProperty = std::move(val);
diff --git a/tests/src/test_report.cpp b/tests/src/test_report.cpp
index af22166..3e6b049 100644
--- a/tests/src/test_report.cpp
+++ b/tests/src/test_report.cpp
@@ -86,7 +86,7 @@
             params.reportUpdates(), *reportManagerMock, storageMock,
             utils::convContainer<std::shared_ptr<interfaces::Metric>>(
                 metricMocks),
-            params.enabled(), std::move(clockFakePtr));
+            params.enabled(), std::move(clockFakePtr), params.triggerIds());
     }
 
     template <class T>
@@ -164,6 +164,9 @@
                 Eq(toReadingParameters(defaultParams.metricParameters())));
     EXPECT_THAT(getProperty<std::string>(sut->getPath(), "Name"),
                 Eq(defaultParams.reportName()));
+    EXPECT_THAT(
+        getProperty<std::vector<std::string>>(sut->getPath(), "TriggerIds"),
+        Eq(std::vector<std::string>()));
 }
 
 TEST_F(TestReport, readingsAreInitialyEmpty)
@@ -253,6 +256,59 @@
     EXPECT_THAT(ec, Eq(boost::system::errc::success));
 }
 
+TEST_F(TestReport, triggerIdsAreUpdatedProperly)
+{
+    sut->updateTriggerIds("trigger1", TriggerIdUpdate::Add);
+    EXPECT_THAT(
+        getProperty<std::vector<std::string>>(sut->getPath(), "TriggerIds"),
+        UnorderedElementsAre("trigger1"));
+
+    sut->updateTriggerIds("trigger2", TriggerIdUpdate::Add);
+    EXPECT_THAT(
+        getProperty<std::vector<std::string>>(sut->getPath(), "TriggerIds"),
+        UnorderedElementsAre("trigger1", "trigger2"));
+
+    sut->updateTriggerIds("trigger3", TriggerIdUpdate::Add);
+    EXPECT_THAT(
+        getProperty<std::vector<std::string>>(sut->getPath(), "TriggerIds"),
+        UnorderedElementsAre("trigger1", "trigger2", "trigger3"));
+
+    sut->updateTriggerIds("trigger1", TriggerIdUpdate::Remove);
+    EXPECT_THAT(
+        getProperty<std::vector<std::string>>(sut->getPath(), "TriggerIds"),
+        UnorderedElementsAre("trigger2", "trigger3"));
+}
+
+TEST_F(TestReport, successWhenRemovingSameTriggerIdMultipleTimes)
+{
+    sut->updateTriggerIds("trigger1", TriggerIdUpdate::Add);
+    sut->updateTriggerIds("trigger2", TriggerIdUpdate::Add);
+    sut->updateTriggerIds("trigger1", TriggerIdUpdate::Remove);
+    sut->updateTriggerIds("trigger1", TriggerIdUpdate::Remove);
+    EXPECT_THAT(
+        getProperty<std::vector<std::string>>(sut->getPath(), "TriggerIds"),
+        UnorderedElementsAre("trigger2"));
+}
+
+TEST_F(TestReport, successWhenRemovingNonExistingTriggerId)
+{
+    sut->updateTriggerIds("trigger1", TriggerIdUpdate::Add);
+    sut->updateTriggerIds("notTrigger", TriggerIdUpdate::Remove);
+    EXPECT_THAT(
+        getProperty<std::vector<std::string>>(sut->getPath(), "TriggerIds"),
+        UnorderedElementsAre("trigger1"));
+}
+
+TEST_F(TestReport, noDuplicatesWhenSameTriggerIdIsAdded)
+{
+    sut->updateTriggerIds("trigger1", TriggerIdUpdate::Add);
+    sut->updateTriggerIds("trigger2", TriggerIdUpdate::Add);
+    sut->updateTriggerIds("trigger1", TriggerIdUpdate::Add);
+    EXPECT_THAT(
+        getProperty<std::vector<std::string>>(sut->getPath(), "TriggerIds"),
+        UnorderedElementsAre("trigger1", "trigger2"));
+}
+
 class TestReportStore :
     public TestReport,
     public WithParamInterface<std::pair<std::string, nlohmann::json>>
@@ -782,3 +838,12 @@
     ASSERT_THAT(storedConfiguration.at("AppendLimit"),
                 Eq(std::numeric_limits<uint64_t>::max()));
 }
+
+TEST_F(TestReportInitialization, triggerIdsPropertyIsInitialzed)
+{
+    sut = makeReport(ReportParams().triggerIds({"trigger1", "trigger2"}));
+
+    EXPECT_THAT(
+        getProperty<std::vector<std::string>>(sut->getPath(), "TriggerIds"),
+        UnorderedElementsAre("trigger1", "trigger2"));
+}
diff --git a/tests/src/test_report_manager.cpp b/tests/src/test_report_manager.cpp
index 10b4de9..bf76efc 100644
--- a/tests/src/test_report_manager.cpp
+++ b/tests/src/test_report_manager.cpp
@@ -1,7 +1,9 @@
 #include "dbus_environment.hpp"
 #include "helpers.hpp"
+#include "interfaces/trigger_manager.hpp"
 #include "mocks/json_storage_mock.hpp"
 #include "mocks/report_factory_mock.hpp"
+#include "mocks/trigger_manager_mock.hpp"
 #include "params/report_params.hpp"
 #include "report.hpp"
 #include "report_manager.hpp"
@@ -29,6 +31,9 @@
         std::make_unique<NiceMock<ReportMock>>(reportParams.reportId());
     ReportMock& reportMock = *reportMockPtr;
 
+    std::unique_ptr<interfaces::TriggerManager> triggerManagerMockPtr =
+        std::make_unique<NiceMock<TriggerManagerMock>>();
+
     std::unique_ptr<ReportManager> sut;
 
     MockFunction<void(std::string)> checkPoint;
@@ -38,9 +43,9 @@
         EXPECT_CALL(reportFactoryMock, convertMetricParams(_, _))
             .Times(AnyNumber());
 
-        sut = std::make_unique<ReportManager>(std::move(reportFactoryMockPtr),
-                                              std::move(storageMockPtr),
-                                              DbusEnvironment::getObjServer());
+        sut = std::make_unique<ReportManager>(
+            std::move(reportFactoryMockPtr), std::move(storageMockPtr),
+            DbusEnvironment::getObjServer(), triggerManagerMockPtr);
     }
 
     void TearDown() override
@@ -378,6 +383,32 @@
     sut->updateReport("NotAReport");
 }
 
+TEST_F(TestReportManager, updateTriggerIdsUpdatesThemForExistReport)
+{
+    reportFactoryMock.expectMake(reportParams, Ref(*sut), Ref(storageMock))
+        .WillOnce(Return(ByMove(std::move(reportMockPtr))));
+    EXPECT_CALL(reportMock, updateTriggerIds("Trigger1", TriggerIdUpdate::Add));
+    EXPECT_CALL(reportMock,
+                updateTriggerIds("Trigger2", TriggerIdUpdate::Remove));
+
+    addReport(reportParams);
+    sut->updateTriggerIds(reportParams.reportId(), "Trigger1",
+                          TriggerIdUpdate::Add);
+
+    sut->updateTriggerIds(reportParams.reportId(), "Trigger2",
+                          TriggerIdUpdate::Remove);
+}
+
+TEST_F(TestReportManager, updateTriggerIdsDoNothingIfReportDoesNotExist)
+{
+    reportFactoryMock.expectMake(reportParams, Ref(*sut), Ref(storageMock))
+        .WillOnce(Return(ByMove(std::move(reportMockPtr))));
+    EXPECT_CALL(reportMock, updateTriggerIds(_, _)).Times(0);
+
+    addReport(reportParams);
+    sut->updateTriggerIds("NotAReport", "Trigger1", TriggerIdUpdate::Add);
+}
+
 class TestReportManagerWithAggregationOperationType :
     public TestReportManager,
     public WithParamInterface<OperationType>
@@ -431,9 +462,9 @@
 
     void makeReportManager()
     {
-        sut = std::make_unique<ReportManager>(std::move(reportFactoryMockPtr),
-                                              std::move(storageMockPtr),
-                                              DbusEnvironment::getObjServer());
+        sut = std::make_unique<ReportManager>(
+            std::move(reportFactoryMockPtr), std::move(storageMockPtr),
+            DbusEnvironment::getObjServer(), triggerManagerMockPtr);
     }
 
     nlohmann::json data = nlohmann::json{
diff --git a/tests/src/test_trigger.cpp b/tests/src/test_trigger.cpp
index a2286ee..5ad2a81 100644
--- a/tests/src/test_trigger.cpp
+++ b/tests/src/test_trigger.cpp
@@ -1,6 +1,7 @@
 #include "dbus_environment.hpp"
 #include "helpers.hpp"
 #include "mocks/json_storage_mock.hpp"
+#include "mocks/report_manager_mock.hpp"
 #include "mocks/sensor_mock.hpp"
 #include "mocks/threshold_mock.hpp"
 #include "mocks/trigger_factory_mock.hpp"
@@ -36,6 +37,8 @@
                     Milliseconds(5).count(), "32.7"},
             });
 
+    std::unique_ptr<ReportManagerMock> reportManagerMockPtr =
+        std::make_unique<NiceMock<ReportManagerMock>>();
     std::unique_ptr<TriggerManagerMock> triggerManagerMockPtr =
         std::make_unique<NiceMock<TriggerManagerMock>>();
     std::unique_ptr<TriggerFactoryMock> triggerFactoryMockPtr =
@@ -70,7 +73,8 @@
                 params.reportIds().begin(), params.reportIds().end()),
             std::vector<std::shared_ptr<interfaces::Threshold>>(thresholdMocks),
             *triggerManagerMockPtr, storageMock, *triggerFactoryMockPtr,
-            SensorMock::makeSensorMocks(params.sensors()));
+            SensorMock::makeSensorMocks(params.sensors()),
+            *reportManagerMockPtr);
     }
 
     static interfaces::JsonStorage::FilePath to_file_path(std::string name)
@@ -132,6 +136,13 @@
                       triggerParams.thresholdParams())));
 }
 
+TEST_F(TestTrigger, checkBasicGetters)
+{
+    EXPECT_THAT(sut->getId(), Eq(triggerParams.id()));
+    EXPECT_THAT(sut->getPath(), Eq(Trigger::triggerDir + triggerParams.id()));
+    EXPECT_THAT(sut->getReportIds(), Eq(triggerParams.reportIds()));
+}
+
 TEST_F(TestTrigger, setPropertyNameToCorrectValue)
 {
     std::string name = "custom name 1234 %^#5";
@@ -148,6 +159,70 @@
     EXPECT_THAT(
         getProperty<std::vector<std::string>>(sut->getPath(), "ReportNames"),
         Eq(newNames));
+    EXPECT_THAT(
+        getProperty<std::vector<std::string>>(sut->getPath(), "ReportNames"),
+        Eq(sut->getReportIds()));
+}
+
+TEST_F(TestTrigger, settingPropertyReportNamesUptadesTriggerIdsInReports)
+{
+    std::vector<std::string> newPropertyVal = {"abc", "one", "two"};
+
+    for (const auto& reportId : newPropertyVal)
+    {
+        EXPECT_CALL(
+            *reportManagerMockPtr,
+            updateTriggerIds(reportId, sut->getId(), TriggerIdUpdate::Add));
+    }
+    for (const auto& reportId : triggerParams.reportIds())
+    {
+        EXPECT_CALL(
+            *reportManagerMockPtr,
+            updateTriggerIds(reportId, sut->getId(), TriggerIdUpdate::Remove));
+    }
+
+    EXPECT_THAT(setProperty(sut->getPath(), "ReportNames", newPropertyVal),
+                Eq(boost::system::errc::success));
+}
+
+TEST_F(TestTrigger, settingPropertyReportNamesWillNotRemoveTriggerIdsInReports)
+{
+    std::vector<std::string> newPropertyVal = triggerParams.reportIds();
+    std::vector<std::string> newNames{"abc", "one", "two"};
+    newPropertyVal.insert(newPropertyVal.end(), newNames.begin(),
+                          newNames.end());
+
+    for (const auto& reportId : newNames)
+    {
+        EXPECT_CALL(
+            *reportManagerMockPtr,
+            updateTriggerIds(reportId, sut->getId(), TriggerIdUpdate::Add));
+    }
+
+    EXPECT_THAT(setProperty(sut->getPath(), "ReportNames", newPropertyVal),
+                Eq(boost::system::errc::success));
+}
+
+TEST_F(TestTrigger,
+       settingPropertyReportNamesToSameValueWillNotUpdateTriggerIdsInReports)
+{
+    std::vector<std::string> newPropertyVal = triggerParams.reportIds();
+
+    EXPECT_CALL(*reportManagerMockPtr, updateTriggerIds(_, _, _)).Times(0);
+
+    EXPECT_THAT(setProperty(sut->getPath(), "ReportNames", newPropertyVal),
+                Eq(boost::system::errc::success));
+}
+
+TEST_F(TestTrigger,
+       DISABLED_settingPropertyReportNamesThrowsExceptionWhenDuplicateReportIds)
+{
+    std::vector<std::string> newPropertyVal{"trigger1", "trigger2", "trigger1"};
+
+    EXPECT_CALL(*reportManagerMockPtr, updateTriggerIds(_, _, _)).Times(0);
+
+    EXPECT_THAT(setProperty(sut->getPath(), "ReportNames", newPropertyVal),
+                Eq(boost::system::errc::invalid_argument));
 }
 
 TEST_F(TestTrigger, setPropertySensors)
@@ -231,6 +306,12 @@
 {
     EXPECT_CALL(storageMock, remove(to_file_path(sut->getId())));
     EXPECT_CALL(*triggerManagerMockPtr, removeTrigger(sut.get()));
+    for (const auto& reportId : triggerParams.reportIds())
+    {
+        EXPECT_CALL(
+            *reportManagerMockPtr,
+            updateTriggerIds(reportId, sut->getId(), TriggerIdUpdate::Remove));
+    }
     auto ec = deleteTrigger(sut->getPath());
     EXPECT_THAT(ec, Eq(boost::system::errc::success));
 }
@@ -252,7 +333,7 @@
                 Eq(persistent));
 }
 
-class TestTriggerErrors : public TestTrigger
+class TestTriggerInitialization : public TestTrigger
 {
   public:
     void SetUp() override
@@ -261,7 +342,8 @@
     nlohmann::json storedConfiguration;
 };
 
-TEST_F(TestTriggerErrors, exceptionDuringTriggerStoreDisablesPersistency)
+TEST_F(TestTriggerInitialization,
+       exceptionDuringTriggerStoreDisablesPersistency)
 {
     EXPECT_CALL(storageMock, store(_, _))
         .WillOnce(Throw(std::runtime_error("Generic error!")));
@@ -271,7 +353,7 @@
     EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistent"), Eq(false));
 }
 
-TEST_F(TestTriggerErrors, creatingTriggerThrowsExceptionWhenIdIsInvalid)
+TEST_F(TestTriggerInitialization, creatingTriggerThrowsExceptionWhenIdIsInvalid)
 {
     EXPECT_CALL(storageMock, store(_, _)).Times(0);
 
@@ -279,6 +361,18 @@
                  sdbusplus::exception::SdBusError);
 }
 
+TEST_F(TestTriggerInitialization, creatingTriggerUpdatesTriggersIdsInReports)
+{
+    for (const auto& reportId : triggerParams.reportIds())
+    {
+        EXPECT_CALL(*reportManagerMockPtr,
+                    updateTriggerIds(reportId, triggerParams.id(),
+                                     TriggerIdUpdate::Add));
+    }
+
+    sut = makeTrigger(triggerParams);
+}
+
 class TestTriggerStore : public TestTrigger
 {
   public:
diff --git a/tests/src/test_trigger_manager.cpp b/tests/src/test_trigger_manager.cpp
index ea4f0b9..efdac65 100644
--- a/tests/src/test_trigger_manager.cpp
+++ b/tests/src/test_trigger_manager.cpp
@@ -123,6 +123,17 @@
     EXPECT_THAT(path, Eq(std::string()));
 }
 
+TEST_F(TestTriggerManager, DISABLED_failToAddTriggerWithDuplicatesInReportsIds)
+{
+    triggerFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
+        .Times(0);
+
+    auto [ec, path] = addTrigger(
+        TriggerParams().reportIds({"trigger1", "trigger2", "trigger1"}));
+    EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument));
+    EXPECT_THAT(path, Eq(std::string()));
+}
+
 TEST_F(TestTriggerManager, addTriggerWithoutIdAndName)
 {
     triggerFactoryMock
@@ -266,7 +277,6 @@
     sut->removeTrigger(&triggerMock);
     checkPoint.Call("end");
 }
-
 class TestTriggerManagerStorage : public TestTriggerManager
 {
   public: