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

Parse addl docker container image info #1127

Merged
merged 10 commits into from
Jun 14, 2018
Merged

Parse addl docker container image info #1127

merged 10 commits into from
Jun 14, 2018

Conversation

mattpag
Copy link
Contributor

@mattpag mattpag commented May 22, 2018

Parse and store three new container_info fields: repository, tag and digest.
More information on the changes in the first commit message.

@mattpag mattpag requested a review from mstemm May 22, 2018 13:09
@@ -763,6 +815,82 @@ bool sinsp_container_manager::parse_docker(sinsp_container_info* container)
container->m_imageid = imgstr.substr(cpos + 1);
}

auto split_container_image = [](const string &image, string &repo, string &tag, string &digest)

Choose a reason for hiding this comment

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

@mattpag : how about breaking this out to a separate function & adding some unit tests to verify the parsing? The test strings will also be a useful way to document what we expect.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure, will do

Copy link
Contributor

@mstemm mstemm left a comment

Choose a reason for hiding this comment

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

Ok, all done reviewing. Take a look at the comments and let me know what you think.

bool qdres = wh_query_docker(m_inspector->get_wmi_handle(),
(char*)message.c_str(),
bool qdres = wh_query_docker(m_inspector->get_wmi_handle(),
(char*)message.c_str(),
Copy link
Contributor

Choose a reason for hiding this comment

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

the variable message doesn't exist any longer, so I don't think this will compile, will it? Maybe you want to keep old line 696 around.

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, this seems to conflict with other uses of get_docker() where you're trying to pass full urls. So I guess url needs to be converted to message.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The parameter url of parse_docker is already the right thing to pass to wh_query_docker, I just missed to change message to url on line 740. Will do.

return sinsp_docker_response::RESP_OK;
}

bool sinsp_container_manager::parse_docker(sinsp_container_info* container)
{
string json;
sinsp_docker_response resp = get_docker("/v1.24", container->m_id, json);
#ifndef CYGWING_AGENT
sinsp_docker_response resp = get_docker("http://dummy" + m_api_version + "/containers/" + container->m_id + "/json", json);
Copy link
Contributor

Choose a reason for hiding this comment

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

You might want to use localhost instead of dummy, just in case some future version of curl tries to do validation of the hostname part.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree, will do

Json::Value root;
Json::Reader reader;
bool parsingSuccessful = reader.parse(json.substr(pos), root);
bool parsingSuccessful = reader.parse(json, root);
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess this searching for the '{' is no longer needed, as you're expecting libcurl to properly return errors? Is it still not required on windows?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure I understand what you mean.
For windows, I'm doing it directly inside get_docker.
When using libcurl is not required because json will already contain only the response json, not the full HTTP response as before, or will fail with errors.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, I see. Sounds good.

if(get_docker("GET /v1.30/images/" + container->m_imageid + "/json?digests=1 HTTP/1.1\r\nHost: docker \r\n\r\n", img_json) == sinsp_docker_response::RESP_OK)
#endif
{
size_t img_pos = img_json.find("{");
Copy link
Contributor

Choose a reason for hiding this comment

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

Given that we removed a similar search for '{' above, can we also remove it here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes I missed to remove it after a refactoring, it's not needed

container->m_imagetag,
container->m_imagedigest);

if(container->m_imagedigest.empty())
Copy link
Contributor

Choose a reason for hiding this comment

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

Just double checking--it's not possible to combine this call to get_docker with the one at the beginning of parse_docker ? I'm guessing the formats differ?

Copy link
Contributor Author

@mattpag mattpag Jun 8, 2018

Choose a reason for hiding this comment

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

I kept them separate because if container->m_image already contain a full qualified image name there's no need to query the images endpoint at all.
Also, note that when using libcurl, we're using HTTP1.1 pipelining so it will be almost the same as doing it in a single get_docker call.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, sounds good. Just making sure.

m_last_flush_time_ns(0)
m_last_flush_time_ns(0),
m_unix_socket_path(string(scap_get_host_root()) + "/var/run/docker.sock"),
m_api_version("/v1.24")
Copy link
Contributor

Choose a reason for hiding this comment

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

I like the change to embed the api version in the object, but if I recall I think the api version depends on the endpoint you're fetching, right? If that's the case, how about having multiple api versions here for the endpoints the object might need to fetch?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think we need an additional api version, 1.24 is fine for both the endpoints we might query (see https://docs.docker.com/engine/api/v1.24/#3-endpoints).

{
#ifndef CYGWING_AGENT
curl_global_init(CURL_GLOBAL_DEFAULT);
Copy link
Contributor

Choose a reason for hiding this comment

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

Now that both mesos and the container object might need to initialize libcurl, do you want to have a single global that does this outside of any particular object? (Not really necessary, but it would be a nice to have).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree, will do

@@ -127,6 +133,9 @@ class sinsp_container_info
string m_name;
string m_image;
string m_imageid;
string m_imagerepo;
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you want to make these "N/A" or similar, instead of blank, in the case where it can't be parsed? Thinking particularly about parsing old capture files where the container json event is missing these fields.

Copy link
Contributor Author

@mattpag mattpag Jun 8, 2018

Choose a reason for hiding this comment

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

Sure, I'll create a default constructor that assign <N/A> to all the string fields.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually, sysdig already print out <N/A> if string fields are empty, isn't it enough?

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh ok, that works then.

@mattpag
Copy link
Contributor Author

mattpag commented Jun 8, 2018

@mstemm PTAL

@mattpag mattpag force-pushed the more-container-info branch from 6a3eb3f to ae6f49f Compare June 12, 2018 12:34
mattpag added 10 commits June 14, 2018 10:19
If they are not already specified in the container endpoint,
query the docker local daemon to retrieve also the repository,
tag and digest of the container image.
Also in this commit, the communication medium to the daemon has
been switched from a manual implementation, hard to mantain, to libcurl.
This also allow us to easily exploit HTTP/1.1 features like pipelining.
When it starts, libcurl will have already been
initialized by the container manager.
@mattpag mattpag force-pushed the more-container-info branch from bb45283 to e3cf1a4 Compare June 14, 2018 08:19
@mattpag mattpag merged commit 678fb9c into dev Jun 14, 2018
@mattpag mattpag deleted the more-container-info branch June 14, 2018 16:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants