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

Addl docker container info #655

Merged
merged 4 commits into from
Sep 12, 2016
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
85 changes: 82 additions & 3 deletions userspace/libsinsp/container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,59 @@ along with sysdig. If not, see <http://www.gnu.org/licenses/>.
#include "sinsp.h"
#include "sinsp_int.h"
#include "container.h"
#include "utils.h"

void sinsp_container_info::parse_json_mounts(const Json::Value &mnt_obj, vector<sinsp_container_info::container_mount_info> &mounts)
{
if(!mnt_obj.isNull() && mnt_obj.isArray())
{
for(uint32_t i=0; i<mnt_obj.size(); i++)
{
const Json::Value &mount = mnt_obj[i];
mounts.emplace_back(mount["Source"], mount["Destination"],
mount["Mode"], mount["RW"],
mount["Propagation"]);
}
}
}

sinsp_container_info::container_mount_info *sinsp_container_info::mount_by_idx(uint32_t idx)
{
if (idx >= m_mounts.size())
{
return NULL;
}

return &(m_mounts[idx]);
}

sinsp_container_info::container_mount_info *sinsp_container_info::mount_by_source(std::string &source)
{
// note: linear search
for (auto &mntinfo :m_mounts)
{
if(sinsp_utils::glob_match(source.c_str(), mntinfo.m_source.c_str()))
{
return &mntinfo;
}
}

return NULL;
}

sinsp_container_info::container_mount_info *sinsp_container_info::mount_by_dest(std::string &dest)
{
// note: linear search
for (auto &mntinfo :m_mounts)
{
if(sinsp_utils::glob_match(dest.c_str(), mntinfo.m_dest.c_str()))
{
return &mntinfo;
}
}

return NULL;
}

sinsp_container_manager::sinsp_container_manager(sinsp* inspector) :
m_inspector(inspector),
Expand All @@ -41,7 +94,7 @@ bool sinsp_container_manager::remove_inactive_containers()
m_last_flush_time_ns = m_inspector->m_lastevent_ts - m_inspector->m_inactive_container_scan_time_ns + 30 * ONE_SECOND_IN_NS;
}

if(m_inspector->m_lastevent_ts >
if(m_inspector->m_lastevent_ts >
m_last_flush_time_ns + m_inspector->m_inactive_thread_scan_time_ns)
{
res = true;
Expand Down Expand Up @@ -187,7 +240,7 @@ bool sinsp_container_manager::resolve_container(sinsp_threadinfo* tinfo, bool qu
if(pos != string::npos)
{
if(cgroup.length() - pos - 1 == 64 &&
cgroup.find_first_not_of("0123456789abcdefABCDEF", pos + 1) == string::npos)
cgroup.find_first_not_of("0123456789abcdefABCDEF", pos + 1) == string::npos)
{
container_info.m_type = CT_DOCKER;
container_info.m_id = cgroup.substr(pos + 1, 12);
Expand Down Expand Up @@ -407,6 +460,24 @@ string sinsp_container_manager::container_to_json(const sinsp_container_info& co
container["type"] = container_info.m_type;
container["name"] = container_info.m_name;
container["image"] = container_info.m_image;
container["privileged"] = container_info.m_privileged;

Json::Value mounts = Json::arrayValue;

for (auto &mntinfo : container_info.m_mounts)
{
Json::Value mount;

mount["Source"] = mntinfo.m_source;
mount["Destination"] = mntinfo.m_dest;
mount["Mode"] = mntinfo.m_mode;
mount["RW"] = mntinfo.m_rdwr;
mount["Propagation"] = mntinfo.m_propagation;

mounts.append(mount);
}

container["Mounts"] = mounts;

char addrbuff[100];
uint32_t iph = ntohl(container_info.m_container_ip);
Expand Down Expand Up @@ -552,7 +623,7 @@ bool sinsp_container_manager::parse_docker(sinsp_container_info* container)
if(v.isArray())
{
for(uint32_t j = 0; j < v.size(); ++j)
{
{
sinsp_container_info::container_port_mapping port_mapping;

ip = v[j]["HostIp"].asString();
Expand Down Expand Up @@ -609,6 +680,14 @@ bool sinsp_container_manager::parse_docker(sinsp_container_info* container)
{
container->m_cpu_period = cpu_period;
}
const Json::Value &privileged = host_config_obj["Privileged"];
if(!privileged.isNull() && privileged.isBool())
{
container->m_privileged = privileged.asBool();
}

sinsp_container_info::parse_json_mounts(root["Mounts"], container->m_mounts);

return true;
}

Expand Down
59 changes: 59 additions & 0 deletions userspace/libsinsp/container.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,57 @@ class sinsp_container_info
uint16_t m_container_port;
};

class container_mount_info
{
public:
container_mount_info():
m_source(""),
m_dest(""),
m_mode(""),
m_rdwr(false),
m_propagation("")
{
}

container_mount_info(const Json::Value &source, const Json::Value &dest,
const Json::Value &mode, const Json::Value &rw,
const Json::Value &propagation)
{
get_string_value(source, m_source);
get_string_value(dest, m_dest);
get_string_value(mode, m_mode);
get_string_value(propagation, m_propagation);

if(!rw.isNull() && rw.isBool())
{
m_rdwr = rw.asBool();
}
}

std::string to_string()
{
return m_source + ":" +
m_dest + ":" +
m_mode + ":" +
(m_rdwr ? "true" : "false") + ":" +
m_propagation;
}

inline void get_string_value(const Json::Value &val, std::string &result)
{
if(!val.isNull() && val.isString())
{
result = val.asString();
}
}

std::string m_source;
std::string m_dest;
std::string m_mode;
bool m_rdwr;
std::string m_propagation;
};

sinsp_container_info():
m_container_ip(0),
m_memory_limit(0),
Expand All @@ -55,11 +106,19 @@ class sinsp_container_info
{
}

static void parse_json_mounts(const Json::Value &mnt_obj, vector<container_mount_info> &mounts);

container_mount_info *mount_by_idx(uint32_t idx);
container_mount_info *mount_by_source(std::string &source);
container_mount_info *mount_by_dest(std::string &dest);

string m_id;
sinsp_container_type m_type;
string m_name;
string m_image;
uint32_t m_container_ip;
bool m_privileged;
Copy link
Contributor

Choose a reason for hiding this comment

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

Are there cases where this member remains uninitialized and the user can read a spurious value?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For non-docker containers, the filtercheck always returns NULL. For docker containers, m_privileged should be set while parsing the results of the GET /containers/XXX/json response.I think the result always has a Privileged field.

Regardless, I should initialize it to false just to make sure. I've got that fix in #658.

Copy link
Contributor

Choose a reason for hiding this comment

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

I was more thinking of a case where you read an old trace file that contains a Docker json blob without the privileged flag and the customer maybe runs sysdig or falco and gets spurious privileged values on that trace, just wanted to make sure that was covered.

vector<container_mount_info> m_mounts;
vector<container_port_mapping> m_port_mappings;
map<string, string> m_labels;
string m_mesos_task_id;
Expand Down
Loading