Proper cache invalidation
This commit is contained in:
parent
befd01cb03
commit
ea4be19a86
@ -74,5 +74,5 @@ class Image:
|
|||||||
|
|
||||||
def layer(self, key):
|
def layer(self, key):
|
||||||
layer = copy.deepcopy(self)
|
layer = copy.deepcopy(self)
|
||||||
layer.tags = [key]
|
layer.tags = ['layer-' + key]
|
||||||
return layer
|
return layer
|
||||||
|
|||||||
@ -144,6 +144,16 @@ class Output:
|
|||||||
'\n',
|
'\n',
|
||||||
]))
|
]))
|
||||||
|
|
||||||
|
def info(self, text):
|
||||||
|
if self.debug is True or 'visit' in str(self.debug):
|
||||||
|
self(''.join([
|
||||||
|
self.colors['cyanbold'],
|
||||||
|
'➤ INFO ',
|
||||||
|
self.colors['reset'],
|
||||||
|
text,
|
||||||
|
'\n',
|
||||||
|
]))
|
||||||
|
|
||||||
def skip(self, action):
|
def skip(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,3 +1,4 @@
|
|||||||
|
import asyncio
|
||||||
import copy
|
import copy
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import os
|
import os
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import asyncio
|
||||||
import copy
|
import copy
|
||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import json
|
||||||
@ -50,54 +51,74 @@ class Buildah(Target):
|
|||||||
os.execvp('buildah', ['buildah', 'unshare'] + sys.argv)
|
os.execvp('buildah', ['buildah', 'unshare'] + sys.argv)
|
||||||
# program has been replaced
|
# program has been replaced
|
||||||
|
|
||||||
actions_done = await self.cache_load(*actions)
|
layers = await self.layers()
|
||||||
|
keep = await self.cache_setup(layers, *actions)
|
||||||
|
keepnames = [*map(lambda x: 'localhost/' + str(x), keep)]
|
||||||
|
self.invalidate = [name for name in layers if name not in keepnames]
|
||||||
|
if self.invalidate:
|
||||||
|
self.output.info('Invalidating old layers')
|
||||||
|
await self.parent.exec(
|
||||||
|
'buildah', 'rmi', *self.invalidate, raises=False)
|
||||||
|
|
||||||
if actions:
|
if actions:
|
||||||
actions = actions[len(actions_done):]
|
actions = actions[len(keep):]
|
||||||
if not actions:
|
if not actions:
|
||||||
self.clean = None
|
return self.uptodate()
|
||||||
self.output.success('Image up to date')
|
|
||||||
return
|
|
||||||
else:
|
else:
|
||||||
self.actions = self.actions[len(actions_done):]
|
self.actions = self.actions[len(keep):]
|
||||||
if not self.actions:
|
if not self.actions:
|
||||||
self.clean = None
|
return self.uptodate()
|
||||||
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.root = Path((await self.parent.exec('buildah', 'mount', self.ctr)).out)
|
self.root = Path((await self.parent.exec('buildah', 'mount', self.ctr)).out)
|
||||||
await super().__call__(*actions)
|
|
||||||
|
|
||||||
async def images(self):
|
return await super().__call__(*actions)
|
||||||
result = await self.parent.exec(
|
|
||||||
'podman image list --format json',
|
def uptodate(self):
|
||||||
|
self.clean = None
|
||||||
|
self.output.success('Image up to date')
|
||||||
|
return
|
||||||
|
|
||||||
|
async def layers(self):
|
||||||
|
ret = set()
|
||||||
|
results = await self.parent.exec(
|
||||||
|
'buildah images --json',
|
||||||
quiet=True,
|
quiet=True,
|
||||||
)
|
)
|
||||||
result = json.loads(result.out)
|
results = json.loads(results.out)
|
||||||
return [item for sublist in result for item in sublist['History']]
|
|
||||||
|
|
||||||
async def cache_load(self, *actions):
|
prefix = 'localhost/' + self.image.repository + ':layer-'
|
||||||
actions_done = []
|
for result in results:
|
||||||
|
if not result.get('names', None):
|
||||||
|
continue
|
||||||
|
for name in result['names']:
|
||||||
|
if name.startswith(prefix):
|
||||||
|
ret.add(name)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
async def cache_setup(self, layers, *actions):
|
||||||
|
keep = []
|
||||||
self.image_previous = Image(self.base)
|
self.image_previous = Image(self.base)
|
||||||
images = await self.images()
|
|
||||||
for action in actions or self.actions:
|
for action in actions or self.actions:
|
||||||
action_image = self.action_image(action)
|
action_image = await self.action_image(action)
|
||||||
if 'localhost/' + str(action_image) in images:
|
name = 'localhost/' + str(action_image)
|
||||||
|
if name in layers:
|
||||||
self.base = self.image_previous = action_image
|
self.base = self.image_previous = action_image
|
||||||
actions_done.append(action)
|
keep.append(action_image)
|
||||||
self.output.skip(f'Found valid cached layer for {action}')
|
self.output.skip(f'Found valid cached layer for {action}')
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
return actions_done
|
return keep
|
||||||
|
|
||||||
def action_image(self, action):
|
async def action_image(self, action):
|
||||||
if self.image_previous:
|
if self.image_previous:
|
||||||
prefix = self.image_previous.tags[0]
|
prefix = self.image_previous.tags[0]
|
||||||
else:
|
else:
|
||||||
prefix = self.base
|
prefix = self.base
|
||||||
if hasattr(action, 'cachehash'):
|
if hasattr(action, 'cachekey'):
|
||||||
action_key = action.cachehash()
|
action_key = action.cachekey()
|
||||||
|
if asyncio.iscoroutine(action_key):
|
||||||
|
action_key = str(await action_key)
|
||||||
else:
|
else:
|
||||||
action_key = str(action)
|
action_key = str(action)
|
||||||
key = prefix + action_key
|
key = prefix + action_key
|
||||||
@ -106,8 +127,14 @@ class Buildah(Target):
|
|||||||
|
|
||||||
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)
|
||||||
action_image = self.action_image(action)
|
action_image = await self.action_image(action)
|
||||||
await self.commit(action_image)
|
await self.parent.exec(
|
||||||
|
'buildah',
|
||||||
|
'commit',
|
||||||
|
'--format=' + action_image.format,
|
||||||
|
self.ctr,
|
||||||
|
action_image,
|
||||||
|
)
|
||||||
self.image_previous = action_image
|
self.image_previous = action_image
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user