Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add changes to persist agent_group information and perform file download requests #224

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/coverage_check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ env:

jobs:
coverage:
runs-on: ubuntu-24
runs-on: ubuntu-24.04

steps:
- name: Checkout code
Expand Down
4 changes: 4 additions & 0 deletions src/agent/agent_info/include/agent_info.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <string>
#include <vector>

class AgentInfo
{
Expand All @@ -11,13 +12,16 @@ class AgentInfo
std::string GetName() const;
std::string GetKey() const;
std::string GetUUID() const;
std::vector<std::string> GetGroups() const;

void SetName(const std::string& name);
void SetKey(const std::string& key);
void SetUUID(const std::string& uuid);
void SetGroups(const std::vector<std::string>& groupList);

private:
std::string m_name;
std::string m_key;
std::string m_uuid;
std::vector<std::string> m_groups;
};
13 changes: 13 additions & 0 deletions src/agent/agent_info/src/agent_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ AgentInfo::AgentInfo()
m_name = agentInfoPersistance.GetName();
m_key = agentInfoPersistance.GetKey();
m_uuid = agentInfoPersistance.GetUUID();
m_groups = agentInfoPersistance.GetGroups();

if (m_uuid.empty())
{
Expand Down Expand Up @@ -47,6 +48,11 @@ std::string AgentInfo::GetUUID() const
return m_uuid;
}

std::vector<std::string> AgentInfo::GetGroups() const
{
return m_groups;
}

void AgentInfo::SetName(const std::string& name)
{
AgentInfoPersistance agentInfoPersistance;
Expand All @@ -67,3 +73,10 @@ void AgentInfo::SetUUID(const std::string& uuid)
agentInfoPersistance.SetUUID(uuid);
m_uuid = uuid;
}

void AgentInfo::SetGroups(const std::vector<std::string>& groupList)
{
AgentInfoPersistance agentInfoPersistance;
agentInfoPersistance.SetGroups(groupList);
m_groups = groupList;
}
96 changes: 86 additions & 10 deletions src/agent/agent_info/src/agent_info_persistance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,28 @@
#include <SQLiteCpp/SQLiteCpp.h>
#include <logger.hpp>

namespace
{
const std::string AGENT_INFO_TABLE_NAME = "agent_info";
const std::string AGENT_GROUP_TABLE_NAME = "agent_group";
} // namespace

AgentInfoPersistance::AgentInfoPersistance(const std::string& dbPath)
{
try
{
m_db = std::make_unique<SQLite::Database>(dbPath, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);

if (!AgentInfoTableExists())
if (!TableExists(AGENT_INFO_TABLE_NAME))
{
CreateAgentInfoTable();
}

if (!TableExists(AGENT_GROUP_TABLE_NAME))
{
CreateAgentGroupTable();
}

if (AgentInfoIsEmpty())
{
InsertDefaultAgentInfo();
Expand All @@ -28,11 +39,11 @@ AgentInfoPersistance::AgentInfoPersistance(const std::string& dbPath)

AgentInfoPersistance::~AgentInfoPersistance() = default;

bool AgentInfoPersistance::AgentInfoTableExists() const
bool AgentInfoPersistance::TableExists(const std::string& table) const
{
try
{
SQLite::Statement query(*m_db, "SELECT name FROM sqlite_master WHERE type='table' AND name='agent_info';");
SQLite::Statement query(*m_db, "SELECT name FROM sqlite_master WHERE type='table' AND name='" + table + "';");
return query.executeStep();
}
catch (const std::exception& e)
Expand All @@ -46,7 +57,7 @@ bool AgentInfoPersistance::AgentInfoIsEmpty() const
{
try
{
SQLite::Statement query(*m_db, "SELECT COUNT(*) FROM agent_info;");
SQLite::Statement query(*m_db, "SELECT COUNT(*) FROM " + AGENT_INFO_TABLE_NAME + ";");
query.executeStep();
const auto count = query.getColumn(0).getInt();
return count == 0;
Expand All @@ -63,7 +74,8 @@ void AgentInfoPersistance::CreateAgentInfoTable()
{
try
{
m_db->exec("CREATE TABLE IF NOT EXISTS agent_info ("
m_db->exec("CREATE TABLE IF NOT EXISTS " + AGENT_INFO_TABLE_NAME +
" ("
"name TEXT, "
"key TEXT, "
"uuid TEXT"
Expand All @@ -75,17 +87,34 @@ void AgentInfoPersistance::CreateAgentInfoTable()
}
}

void AgentInfoPersistance::CreateAgentGroupTable()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a table for the agent group? Can't it be just another column in the agent_info table?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that in the future more information related to the groups could be added, for example the hash of the configuration file of each group to check that it has not been modified. That's why I thought about adding a new table.

{
try
{
m_db->exec("CREATE TABLE IF NOT EXISTS " + AGENT_GROUP_TABLE_NAME +
sdvendramini marked this conversation as resolved.
Show resolved Hide resolved
" ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"name TEXT NOT NULL UNIQUE"
");");
}
catch (const std::exception& e)
{
LogError("Error creating table: {}.", e.what());
}
}

void AgentInfoPersistance::InsertDefaultAgentInfo()
{
try
{
SQLite::Statement query(*m_db, "SELECT COUNT(*) FROM agent_info;");
SQLite::Statement query(*m_db, "SELECT COUNT(*) FROM " + AGENT_INFO_TABLE_NAME + ";");
query.executeStep();
const auto count = query.getColumn(0).getInt();

if (count == 0)
{
SQLite::Statement insert(*m_db, "INSERT INTO agent_info (name, key, uuid) VALUES (?, ?, ?);");
SQLite::Statement insert(*m_db,
"INSERT INTO " + AGENT_INFO_TABLE_NAME + " (name, key, uuid) VALUES (?, ?, ?);");
insert.exec();
}
}
Expand All @@ -99,7 +128,7 @@ void AgentInfoPersistance::SetAgentInfoValue(const std::string& column, const st
{
try
{
SQLite::Statement query(*m_db, "UPDATE agent_info SET " + column + " = ?;");
SQLite::Statement query(*m_db, "UPDATE " + AGENT_INFO_TABLE_NAME + " SET " + column + " = ?;");
query.bind(1, value);
query.exec();
}
Expand All @@ -114,7 +143,7 @@ std::string AgentInfoPersistance::GetAgentInfoValue(const std::string& column) c
std::string value;
try
{
SQLite::Statement query(*m_db, "SELECT " + column + " FROM agent_info LIMIT 1;");
SQLite::Statement query(*m_db, "SELECT " + column + " FROM " + AGENT_INFO_TABLE_NAME + " LIMIT 1;");
if (query.executeStep())
{
value = query.getColumn(0).getText();
Expand Down Expand Up @@ -142,6 +171,27 @@ std::string AgentInfoPersistance::GetUUID() const
return GetAgentInfoValue("uuid");
}

std::vector<std::string> AgentInfoPersistance::GetGroups() const
{
std::vector<std::string> groupList;

try
{
SQLite::Statement query(*m_db, "SELECT name FROM " + AGENT_GROUP_TABLE_NAME + " ORDER BY id ASC;");

while (query.executeStep())
{
groupList.push_back(query.getColumn(0).getString());
}
}
catch (const std::exception& e)
{
LogError("Error getting agent group list: {}.", e.what());
}

return groupList;
}

void AgentInfoPersistance::SetName(const std::string& name)
{
SetAgentInfoValue("name", name);
Expand All @@ -157,11 +207,37 @@ void AgentInfoPersistance::SetUUID(const std::string& uuid)
SetAgentInfoValue("uuid", uuid);
}

void AgentInfoPersistance::SetGroups(const std::vector<std::string>& groupList)
{
try
{
SQLite::Transaction transaction(*m_db);

m_db->exec("DELETE FROM " + AGENT_GROUP_TABLE_NAME + ";");
jr0me marked this conversation as resolved.
Show resolved Hide resolved

SQLite::Statement query(*m_db, "INSERT INTO " + AGENT_GROUP_TABLE_NAME + " (name) VALUES (?);");

for (const std::string& group : groupList)
{
query.bind(1, group);
query.exec();
query.reset();
}

transaction.commit();
}
catch (const std::exception& e)
{
LogError("Error inserting group: {}.", e.what());
}
}

void AgentInfoPersistance::ResetToDefault()
{
try
{
m_db->exec("DELETE FROM agent_info;");
m_db->exec("DELETE FROM " + AGENT_INFO_TABLE_NAME + ";");
m_db->exec("DELETE FROM " + AGENT_GROUP_TABLE_NAME + ";");
InsertDefaultAgentInfo();
}
catch (const std::exception& e)
Expand Down
6 changes: 5 additions & 1 deletion src/agent/agent_info/src/agent_info_persistance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <memory>
#include <string>
#include <vector>

static constexpr char sqlitedb_path[] = "agent_info.db";

Expand All @@ -24,17 +25,20 @@ class AgentInfoPersistance
std::string GetName() const;
std::string GetKey() const;
std::string GetUUID() const;
std::vector<std::string> GetGroups() const;

void SetName(const std::string& name);
void SetKey(const std::string& key);
void SetUUID(const std::string& uuid);
void SetGroups(const std::vector<std::string>& groupList);

void ResetToDefault();

private:
bool AgentInfoTableExists() const;
bool TableExists(const std::string& table) const;
bool AgentInfoIsEmpty() const;
void CreateAgentInfoTable();
void CreateAgentGroupTable();
void InsertDefaultAgentInfo();
void SetAgentInfoValue(const std::string& column, const std::string& value);
std::string GetAgentInfoValue(const std::string& column) const;
Expand Down
17 changes: 17 additions & 0 deletions src/agent/agent_info/tests/agent_info_persistance_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,23 @@ TEST_F(AgentInfoPersistanceTest, TestSetUUID)
EXPECT_EQ(persistance->GetUUID(), newUUID);
}

TEST_F(AgentInfoPersistanceTest, TestSetGroups)
{
const std::vector<std::string> newGroups = {"group_1", "group_2"};
persistance->SetGroups(newGroups);
EXPECT_EQ(persistance->GetGroups(), newGroups);
}

TEST_F(AgentInfoPersistanceTest, TestSetGroupsDelete)
{
const std::vector<std::string> oldGroups = {"group_1", "group_2"};
const std::vector<std::string> newGroups = {"group_3", "group_4"};
persistance->SetGroups(oldGroups);
EXPECT_EQ(persistance->GetGroups(), oldGroups);
persistance->SetGroups(newGroups);
EXPECT_EQ(persistance->GetGroups(), newGroups);
}

TEST_F(AgentInfoPersistanceTest, TestResetToDefault)
{
const std::string newName = "new_name";
Expand Down
12 changes: 12 additions & 0 deletions src/agent/agent_info/tests/agent_info_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,18 @@ TEST_F(AgentInfoTest, TestSetUUID)
EXPECT_EQ(agentInfoReloaded.GetUUID(), newUUID);
}

TEST_F(AgentInfoTest, TestSetGroups)
{
AgentInfo agentInfo;
const std::vector<std::string> newGroups = {"t_group_1", "t_group_2"};

agentInfo.SetGroups(newGroups);
EXPECT_EQ(agentInfo.GetGroups(), newGroups);

const AgentInfo agentInfoReloaded;
EXPECT_EQ(agentInfoReloaded.GetGroups(), newGroups);
}

int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
Expand Down
1 change: 1 addition & 0 deletions src/agent/communicator/include/communicator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ namespace communicator
boost::asio::awaitable<void>
StatelessMessageProcessingTask(std::function<boost::asio::awaitable<std::string>()> getMessages,
std::function<void(const std::string&)> onSuccess);
bool GetGroupConfigurationFromManager(const std::string& groupName, const std::string& dstFilePath);

void Stop();

Expand Down
3 changes: 3 additions & 0 deletions src/agent/communicator/include/http_client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ namespace http_client
const std::string& password,
const bool useHttps) override;

boost::beast::http::response<boost::beast::http::dynamic_body>
PerformHttpRequestDownload(const HttpRequestParams& params, const std::string& dstFilePath) override;

private:
std::shared_ptr<IHttpResolverFactory> m_resolverFactory;
std::shared_ptr<IHttpSocketFactory> m_socketFactory;
Expand Down
3 changes: 3 additions & 0 deletions src/agent/communicator/include/ihttp_client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,8 @@ namespace http_client
const std::string& user,
const std::string& password,
const bool useHttps) = 0;

virtual boost::beast::http::response<boost::beast::http::dynamic_body>
PerformHttpRequestDownload(const HttpRequestParams& params, const std::string& dstFilePath) = 0;
};
} // namespace http_client
3 changes: 3 additions & 0 deletions src/agent/communicator/include/ihttp_socket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ namespace http_client

virtual void Read(boost::beast::http::response<boost::beast::http::dynamic_body>& res) = 0;

virtual void ReadToFile(boost::beast::http::response_parser<boost::beast::http::dynamic_body>& res,
jr0me marked this conversation as resolved.
Show resolved Hide resolved
const std::string& dstFilePath) = 0;

virtual boost::asio::awaitable<void>
AsyncRead(boost::beast::http::response<boost::beast::http::dynamic_body>& res,
boost::beast::error_code& ec) = 0;
Expand Down
16 changes: 16 additions & 0 deletions src/agent/communicator/src/communicator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,22 @@ namespace communicator
}
}

bool Communicator::GetGroupConfigurationFromManager(const std::string& groupName, const std::string& dstFilePath)
{
const auto reqParams = http_client::HttpRequestParams(boost::beast::http::verb::get,
m_managerIp,
m_port,
"/api/v1/files?file_name=" + groupName + ".conf",
m_useHttps,
*m_token,
"",
"");

const auto result = m_httpClient->PerformHttpRequestDownload(reqParams, dstFilePath);

return result.result() == boost::beast::http::status::ok;
}

void Communicator::Stop()
{
m_keepRunning.store(false);
Expand Down
Loading
Loading