From 82b224ea45bc05869d65202ac8ff800159aff4c7 Mon Sep 17 00:00:00 2001 From: Tomas Tomecek Date: Sat, 11 Jun 2016 19:42:48 +0200 Subject: [PATCH] understand 1.11 layering syntax resolves #82 #74 --- sen/docker_backend.py | 36 ++++++++++++++++++++++++++++++++++-- sen/tui/buffer.py | 3 +++ sen/tui/ui.py | 1 + sen/tui/widgets/info.py | 29 ++++++++++++++++++++--------- sen/tui/widgets/tree.py | 2 ++ 5 files changed, 60 insertions(+), 11 deletions(-) diff --git a/sen/docker_backend.py b/sen/docker_backend.py index 693b3fa..3ea6c23 100644 --- a/sen/docker_backend.py +++ b/sen/docker_backend.py @@ -277,6 +277,33 @@ def parent_image(self): else: return self.docker_backend.scratch_image + @property + def layers(self): + """ + similar as parent images, except that it uses /history API endpoint + :return: + """ + # sample output: + # { + # "Created": 1457116802, + # "Id": "sha256:507cb13a216097710f0d234668bf64a4c92949c573ba15eba13d05aad392fe04", + # "Size": 204692029, + # "Tags": [ + # "docker.io/fedora:latest" + # ], + # "Comment": "", + # "CreatedBy": "/bin/sh -c #(nop) ADD file:bcb5e5c... in /" + # } + response = self.d.history(self.image_id) + layers = [] + for l in response: + layer_id = l["Id"] + if layer_id == "": + layers.append(DockerImage(l, self.docker_backend)) + else: + layers.append(self.docker_backend.get_image_by_id(layer_id)) + return layers + @property def children(self): return self.docker_backend.get_images_for_parent(self) @@ -311,6 +338,10 @@ def command(self): @property def container_command(self): + # history item + created_by = graceful_chain_get(self.data, "CreatedBy") + if created_by: + return created_by inspect = self.inspect(cached=True).response cmd = graceful_chain_get(inspect, "ContainerConfig", "Cmd") if cmd: @@ -324,7 +355,7 @@ def size(self): :return: int """ - return self.data["VirtualSize"] + return self.data.get("VirtualSize", 0) @property def names(self): @@ -332,7 +363,8 @@ def names(self): self._names = [] if self.data is None: return self._names - for t in self.data["RepoTags"]: + # RepoTags = image, Tags = output from `history` command, Tags can be None + for t in self.data.get("RepoTags", self.data.get("Tags")) or []: image_name = ImageNameStruct.parse(t) if image_name.to_str(): self._names.append(image_name) diff --git a/sen/tui/buffer.py b/sen/tui/buffer.py index d11198b..ca4d0d0 100644 --- a/sen/tui/buffer.py +++ b/sen/tui/buffer.py @@ -119,6 +119,9 @@ def __init__(self, docker_image, ui): """ if isinstance(docker_image, RootImage): raise NotifyError("Image \"scratch\" doesn't provide any more information.") + if docker_image.image_id == "": + raise NotifyError("This image (layer) is not available due to changes in docker-1.10 " + "image representation.") self.display_name = docker_image.short_name self.widget = ImageInfoWidget(ui, docker_image) super().__init__() diff --git a/sen/tui/ui.py b/sen/tui/ui.py index d81ee74..cbb4875 100644 --- a/sen/tui/ui.py +++ b/sen/tui/ui.py @@ -317,6 +317,7 @@ def keypress(self, size, key): selected_widget = getattr(self.current_buffer, "widget", None) if selected_widget: focused_docker_object = getattr(self.current_buffer.widget, "focused_docker_object", None) + logger.debug("focused docker object is %s", focused_docker_object) try: self.run_command_by_key( key, diff --git a/sen/tui/widgets/info.py b/sen/tui/widgets/info.py index e181094..2c3634a 100644 --- a/sen/tui/widgets/info.py +++ b/sen/tui/widgets/info.py @@ -9,6 +9,7 @@ import urwid import urwidtrees +from sen.docker_backend import RootImage from sen.tui.widgets.list.base import WidgetBase from urwid.decoration import BoxAdapter @@ -89,16 +90,26 @@ def _layers(self): self.walker.append(RowWidget([SelectableText("Layers", maps=get_map("main_list_white"))])) i = self.docker_image + parent = i.parent_image + layers = self.docker_image.layers index = 0 - self.walker.append(RowWidget([LayerWidget(self.ui, self.docker_image, index=index)])) - while True: - index += 1 - parent = i.parent_image - if parent: - self.walker.append(RowWidget([LayerWidget(self.ui, parent, index=index)])) - i = parent - else: - break + + if isinstance(parent, RootImage) and len(layers) > 0: # pulled image, docker 1.10+ + for image in layers: + self.walker.append( + RowWidget([LayerWidget(self.ui, image, index=index)]) + ) + index += 1 + else: + self.walker.append(RowWidget([LayerWidget(self.ui, self.docker_image, index=index)])) + while True: + index += 1 + parent = i.parent_image + if parent: + self.walker.append(RowWidget([LayerWidget(self.ui, parent, index=index)])) + i = parent + else: + break def _labels(self): if not self.docker_image.labels: diff --git a/sen/tui/widgets/tree.py b/sen/tui/widgets/tree.py index e856a74..f2d92cc 100644 --- a/sen/tui/widgets/tree.py +++ b/sen/tui/widgets/tree.py @@ -17,6 +17,8 @@ def __init__(self, ui, docker_image): class TreeBackend(urwidtrees.Tree): + # FIXME: rewrite to use SimpleTree instead (for sake of docker-1.10 changes: how does one + # index an image with id def __init__(self, docker_backend, ui): super().__init__() self.ui = ui