fixup! Add layer caching
This commit is contained in:
parent
02e9ac6683
commit
2dc00dc2cd
@ -163,9 +163,3 @@ class Packages:
|
|||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'Packages({self.packages}, upgrade={self.upgrade})'
|
return f'Packages({self.packages}, upgrade={self.upgrade})'
|
||||||
|
|
||||||
def layerhasher(self, parent=None):
|
|
||||||
import hashlib
|
|
||||||
blurb = (parent or '') + repr(self)
|
|
||||||
sha1 = hashlib.sha1(blurb.encode('ascii'))
|
|
||||||
return sha1.hexdigest()
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import copy
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
@ -74,3 +75,8 @@ class Image:
|
|||||||
|
|
||||||
for tag in self.tags:
|
for tag in self.tags:
|
||||||
await action.exec('buildah', 'push', f'{self.repository}:{tag}')
|
await action.exec('buildah', 'push', f'{self.repository}:{tag}')
|
||||||
|
|
||||||
|
def layer(self, key):
|
||||||
|
layer = copy.deepcopy(self)
|
||||||
|
layer.tags = [key]
|
||||||
|
return layer
|
||||||
|
|||||||
@ -141,6 +141,16 @@ class Output:
|
|||||||
'\n',
|
'\n',
|
||||||
]))
|
]))
|
||||||
|
|
||||||
|
def skip(self, action):
|
||||||
|
if self.debug is True or 'visit' in str(self.debug):
|
||||||
|
self(''.join([
|
||||||
|
self.colors['yellowbold'],
|
||||||
|
'↪️ SKIP ',
|
||||||
|
self.colors['reset'],
|
||||||
|
self.colorized(action),
|
||||||
|
'\n',
|
||||||
|
]))
|
||||||
|
|
||||||
def success(self, action):
|
def success(self, action):
|
||||||
if self.debug is True or 'visit' in str(self.debug):
|
if self.debug is True or 'visit' in str(self.debug):
|
||||||
self(''.join([
|
self(''.join([
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import copy
|
import copy
|
||||||
|
import hashlib
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
@ -11,6 +12,8 @@ from ..proc import Proc
|
|||||||
|
|
||||||
|
|
||||||
class Buildah(Target):
|
class Buildah(Target):
|
||||||
|
"""Build container image with buildah"""
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
*actions,
|
*actions,
|
||||||
base=None, commit=None,
|
base=None, commit=None,
|
||||||
@ -51,50 +54,64 @@ class Buildah(Target):
|
|||||||
|
|
||||||
if actions:
|
if actions:
|
||||||
actions = actions[len(actions_done):]
|
actions = actions[len(actions_done):]
|
||||||
|
if not actions:
|
||||||
|
self.clean = None
|
||||||
|
self.output.success('Image up to date')
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
self.actions = self.actions[len(actions_done):]
|
self.actions = self.actions[len(actions_done):]
|
||||||
|
if not self.actions:
|
||||||
|
self.clean = None
|
||||||
|
self.output.success('Image up to date')
|
||||||
|
return
|
||||||
|
|
||||||
self.ctr = (await self.parent.exec('buildah', 'from', self.base)).out
|
self.ctr = (await self.parent.exec('buildah', 'from', self.base)).out
|
||||||
self.mnt = Path((await self.parent.exec('buildah', 'mount', self.ctr)).out)
|
self.mnt = Path((await self.parent.exec('buildah', 'mount', self.ctr)).out)
|
||||||
await super().__call__(*actions)
|
await super().__call__(*actions)
|
||||||
|
|
||||||
async def cache_load(self, *actions):
|
async def images(self):
|
||||||
actions_done = []
|
|
||||||
result = await self.parent.exec(
|
result = await self.parent.exec(
|
||||||
'podman image list --format json',
|
'podman image list --format json',
|
||||||
quiet=True,
|
quiet=True,
|
||||||
)
|
)
|
||||||
result = json.loads(result.out)
|
result = json.loads(result.out)
|
||||||
images = [item for sublist in result for item in sublist['History']]
|
return [item for sublist in result for item in sublist['History']]
|
||||||
self.hash_previous = None
|
|
||||||
for action in actions or self.actions:
|
|
||||||
hasher = getattr(action, 'layerhasher', None)
|
|
||||||
if not hasher:
|
|
||||||
break
|
|
||||||
layerhash = hasher(self.hash_previous)
|
|
||||||
layerimage = copy.deepcopy(self.image)
|
|
||||||
layerimage.tags = [layerhash]
|
|
||||||
if 'localhost/' + str(layerimage) in images:
|
|
||||||
self.base = str(layerimage)
|
|
||||||
self.hash_previous = layerhash
|
|
||||||
actions_done.append(action)
|
|
||||||
self.output.success(f'Found cached layer for {action}')
|
|
||||||
|
|
||||||
|
async def cache_load(self, *actions):
|
||||||
|
actions_done = []
|
||||||
|
self.image_previous = Image(self.base)
|
||||||
|
images = await self.images()
|
||||||
|
for action in actions or self.actions:
|
||||||
|
action_image = self.action_image(action)
|
||||||
|
if 'localhost/' + str(action_image) in images:
|
||||||
|
self.base = self.image_previous = action_image
|
||||||
|
actions_done.append(action)
|
||||||
|
self.output.skip(f'Found valid cached layer for {action}')
|
||||||
|
else:
|
||||||
|
break
|
||||||
return actions_done
|
return actions_done
|
||||||
|
|
||||||
|
def action_image(self, action):
|
||||||
|
if self.image_previous:
|
||||||
|
prefix = self.image_previous.tags[0]
|
||||||
|
else:
|
||||||
|
prefix = self.base
|
||||||
|
key = prefix + repr(action)
|
||||||
|
sha1 = hashlib.sha1(key.encode('ascii'))
|
||||||
|
return self.image.layer(sha1.hexdigest())
|
||||||
|
|
||||||
async def action(self, action, reraise=False):
|
async def action(self, action, reraise=False):
|
||||||
result = await super().action(action, reraise)
|
result = await super().action(action, reraise)
|
||||||
hasher = getattr(action, 'layerhasher', None)
|
action_image = self.action_image(action)
|
||||||
if hasher:
|
await self.commit(action_image)
|
||||||
layerhash = hasher(self.hash_previous if self.hash_previous else None)
|
self.image_previous = action_image
|
||||||
layerimage = copy.deepcopy(self.image)
|
|
||||||
layerimage.tags = [layerhash]
|
|
||||||
await self.commit(layerimage)
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
async def clean(self, target):
|
async def clean(self, target):
|
||||||
for src, dst in self.mounts.items():
|
for src, dst in self.mounts.items():
|
||||||
await self.parent.exec('umount', self.mnt / str(dst)[1:])
|
await self.parent.exec('umount', self.mnt / str(dst)[1:])
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
if self.result.status == 'success':
|
if self.result.status == 'success':
|
||||||
await self.commit()
|
await self.commit()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user