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

get container metadata from docker metadata #210

Merged
merged 6 commits into from
May 23, 2018

Conversation

rpitonak
Copy link
Collaborator

  • get_container_metadata implemented in Docker backend
  • minor change in ContainerMetadata, port_mappings is now dict {"host_port": [list_of_container_ports]}
  • test is provided

We need to discuss the naming of methods here, get_metadata and get_container_metadata sounds similar what can be confusing for users.

Copy link
Member

@TomasTomecek TomasTomecek left a comment

Choose a reason for hiding this comment

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

Wow, pretty good progress!

@@ -47,8 +47,8 @@ def __init__(self, name=None, identifier=None, labels=None, command=None,
:param env_variables: dict, {name: value}
:param image: Image, reference to Image instance
:param exposed_ports: list, list of exposed ports
:param port_mappings: dict, dictionary of port mappings {"host_port": "container_port"}, example:
- {"8080":"80"} map port 80 in the container to port 8080 on the host
:param port_mappings: dict, dictionary of port mappings {"host_port": ["container_port"]}, example:
Copy link
Member

Choose a reason for hiding this comment

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

Hm, this doesn't make much sense to me. How could one external port be mapped to two internal?

@@ -475,3 +490,69 @@ def write_to_stdin(self, message):
self.popen_instance.stdin.flush()
except subprocess.CalledProcessError as e:
raise ConuException(e)

def get_container_metadata(self):
Copy link
Member

Choose a reason for hiding this comment

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

I believe we discussed this with @dhodovsk and my suggestion was to break backwards compatibility: .get_metadata method would return instance of the Metadata class, and .inspect method would yield the dict from docker. WDYT?

Copy link
Member

Choose a reason for hiding this comment

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

Agreed, get_metadata() can be used for conu-metadata. I'd suggest adding new commit that would rename all get_metadata() to inspect().


docker_metadata = self.get_metadata(refresh=True)

print(docker_metadata)
Copy link
Member

Choose a reason for hiding this comment

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

probably a leftover from debugging

# ['DISTTAG=f26container', 'FGC=f26']
env_variables = dict()
for env_variable in docker_metadata['Config']['Env']:
env_variables.update({env_variable.split('=')[0]: env_variable.split('=')[1]})
Copy link
Member

Choose a reason for hiding this comment

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

I advise to do .split("=", 1) since = can be put also in the value; the other potential error could occur if the value is unset

Please add these two cases to tests.

Real example:

            "Env": [
                "ASD=",
                "A=B=C=D",
                "XYZ",
                "DISTTAG=f28container",
                "FGC=f28"
            ],
$ env
A=B=C=D
HOSTNAME=36256ed1fe0d
PWD=/
HOME=/root
DISTTAG=f28container
ASD=
FGC=f28
TERM=xterm
SHLVL=1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
_=/usr/bin/env

status = ContainerStatus.CREATED

if docker_metadata['State']['Status'] == 'created':
status = ContainerStatus.CREATED
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure whether we should copy all the possible status from docker just like that. I would love to discuss this next week during our call.

Copy link
Member

Choose a reason for hiding this comment

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

On meeting we decided on 4 states:

  • Running
  • Not-Running (Stopped, Created, Exited - with 0 code)
  • Unknown (Restarting, Terminating,...)
  • Failed

status = ContainerStatus.DEAD

# format of Port mappings from docker inspect:
# {'12345/tcp': [{'HostIp': '0.0.0.0', 'HostPort': '123'}, {'HostIp': '0.0.0.0', 'HostPort': '1234'}]}
Copy link
Member

Choose a reason for hiding this comment

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

see, it's actually the other way around: multiple host ports can point to a single container port

assert container_metadata.status == ContainerStatus.RUNNING

c.delete(force=True)
Copy link
Member

Choose a reason for hiding this comment

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

this should be in finally: block

@user-cont user-cont deleted a comment May 18, 2018
@rpitonak
Copy link
Collaborator Author

rpitonak commented May 18, 2018

Thank you for the review. I pushed some new changes.

We can discuss name of the methods and ContainerStatus on next meeting. I totally agree to not copy all fields from docker but make it more general.

@@ -475,3 +490,69 @@ def write_to_stdin(self, message):
self.popen_instance.stdin.flush()
except subprocess.CalledProcessError as e:
raise ConuException(e)

def get_container_metadata(self):
Copy link
Member

Choose a reason for hiding this comment

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

Agreed, get_metadata() can be used for conu-metadata. I'd suggest adding new commit that would rename all get_metadata() to inspect().


status = ContainerStatus.CREATED

if docker_metadata['State']['Status'] == 'created':
Copy link
Member

Choose a reason for hiding this comment

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

This could be a method on ContainerStatus -> status = ContainerStatus.get(string)

for env_variable in docker_metadata['Config']['Env']:
try:
env_variables.update({env_variable.split('=', 1)[0]: env_variable.split('=', 1)[1]})
except IndexError:
Copy link
Member

Choose a reason for hiding this comment

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

Is this expected? If not, we should raise something.

if key in port_mappings.keys():
port_mappings[key].append(int(item['HostPort']))
else:
port_mappings.update({key: [int(item['HostPort'])]})
Copy link
Member

Choose a reason for hiding this comment

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

This fails when inspecting container that is created with docker run -p 80 nginx

creation_timestamp=docker_metadata['Created'],
env_variables=env_variables,
image=image,
exposed_ports=list(docker_metadata['Config']['ExposedPorts'].keys()),
Copy link
Member

Choose a reason for hiding this comment

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

When there are no exposed ports on container, this field is missing in inspect and get_container_metadata() fails on KeyError

assert container_metadata.hostname == "my_hostname"
assert "XYZ" not in list(container_metadata.env_variables.keys())
assert container_metadata.port_mappings["1234"] == "12345/tcp"
Copy link
Member

Choose a reason for hiding this comment

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

container_metadata.port_mappings actually returns {'12345/tcp': [1234, 123]} in this case.

@psklenar
Copy link
Collaborator

jenkins/superCI comment

  • Status: failure, return code = 1
  • Result url: https://da.gd/3sTbH
  • Comment: See details for logs

@user-cont user-cont deleted a comment May 22, 2018
@user-cont user-cont deleted a comment May 22, 2018
@user-cont user-cont deleted a comment May 22, 2018
@user-cont user-cont deleted a comment May 22, 2018
@user-cont user-cont deleted a comment May 22, 2018
@user-cont user-cont deleted a comment May 22, 2018
@user-cont user-cont deleted a comment May 22, 2018
@user-cont user-cont deleted a comment May 22, 2018
@user-cont user-cont deleted a comment May 22, 2018
@user-cont user-cont deleted a comment May 22, 2018
@user-cont user-cont deleted a comment May 22, 2018
@user-cont user-cont deleted a comment May 22, 2018
@user-cont user-cont deleted a comment May 22, 2018
@user-cont user-cont deleted a comment May 22, 2018
@dhodovsk
Copy link
Member

The requested changes were addressed, it looks good! Thank you!

@@ -433,7 +439,7 @@ def get_status(self):

:return: one of: 'created', 'restarting', 'running', 'paused', 'exited', 'dead'
"""
return self.get_metadata(refresh=True)["State"]["Status"]
return self.inspect(refresh=True)["State"]["Status"]
Copy link
Member

Choose a reason for hiding this comment

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

Would be awesome to use .get_metadata for these. Not blocking this PR,

@TomasTomecek TomasTomecek merged commit 3dd9575 into user-cont:master May 23, 2018
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.

None yet

4 participants