Skip to content

Instantly share code, notes, and snippets.

@adisbladis
Created October 2, 2018 08:22
Embed
What would you like to do?
with import <nixpkgs> { };
let
cutPoints = builtins.map (drv: drv.outPath) [
nodejs
python2
python3
coreutils
openssl.out
glibc
bash
gcc-unwrapped.lib
bzip2.out
];
mkContentsDrv = contents: symlinkJoin {
name = "container-env";
paths = (if builtins.isList contents then contents else [ contents ]);
};
mkLayers = contents: cutPoints: runCommand "closure-paths" {
cutJSON = writeText "cuts" (builtins.toJSON cutPoints);
passAsFile = [ "cutJSON" ];
exportReferencesGraph.graph = contents;
__structuredAttrs = true;
PATH = "${coreutils}/bin:${python3}/bin";
builder = builtins.toFile "builder" ''
. .attrs.sh
cat $cutJSON
python3 ${./make_layers.py} --graph .attrs.json --cuts $cutJSON > outf
mv outf ''${outputs[out]}
'';
} "";
mkDockerImage = contents: let
aggDrv = mkContentsDrv contents;
layers = mkLayers aggDrv cutPoints;
in layers;
drv = (python3.withPackages(ps: [ ps.flake8 ]));
in mkDockerImage [ drv ]
// Example of what the above could would output at the moment
{
"/nix/store/s3nl02c26303mfjvaaxnc19f8ks9hc8c-python3-3.6.6": [
"/nix/store/6v0w8pn91zqdm2ri7wgrlg3y16gqsbij-xz-5.2.4",
"/nix/store/78d783wx27w2ql4pcdq5pxz372ajksgm-sqlite-3.24.0",
"/nix/store/8myyhvyvb93kpdv3valpxb81n08a7mqj-readline-6.3p08",
"/nix/store/8nalpyx6f8arkmh23wx5bc46p6xgqp64-expat-2.2.6",
"/nix/store/bv6znzsv2qkbcwwa251dx7n5dshz3nr3-zlib-1.2.11",
"/nix/store/jsps5n2s3bc5i466k5vvqg4wl5013xms-libffi-3.2.1",
"/nix/store/s3nl02c26303mfjvaaxnc19f8ks9hc8c-python3-3.6.6",
"/nix/store/sr2hxkjn4f3y17safsxy3nwf8iv55jyn-ncurses-6.1",
"/nix/store/vc7rd7zlhmw8mv61sjx0x633dwzlmkww-gdbm-1.17"
],
"/nix/store/2xdf4mgczzfjwj1fmcz0jjx7plvvcgsq-coreutils-8.29": [
"/nix/store/2xdf4mgczzfjwj1fmcz0jjx7plvvcgsq-coreutils-8.29",
"/nix/store/gzxckycv7v43aa1pf0manyva5p58nd4m-attr-2.4.47",
"/nix/store/xbnwfn8dslrmq9w39k3a52bdvigwqx23-acl-2.2.52"
],
"/nix/store/fg4yq8i8wd08xg3fy58l6q73cjy8hjr2-glibc-2.27": [
"/nix/store/fg4yq8i8wd08xg3fy58l6q73cjy8hjr2-glibc-2.27"
],
"/nix/store/czx8vkrb9jdgjyz8qfksh10vrnqa723l-bash-4.4-p23": [
"/nix/store/czx8vkrb9jdgjyz8qfksh10vrnqa723l-bash-4.4-p23"
],
"/nix/store/arrv4xka8hgd65hva6fhlhjkyv74zjp9-container-env": [
"/nix/store/2d1ng0mak79qakfz91s9gzzbq9i6l5gd-python3.6-flake8-3.5.0",
"/nix/store/4f1sgfkjmfvmw9lz213rfqr6zm8gp6h6-python3-3.6.6-env",
"/nix/store/9x3vj2c1k0xn2cyfyvzs7j74a3plhck5-python3.6-setuptools-40.2.0",
"/nix/store/arrv4xka8hgd65hva6fhlhjkyv74zjp9-container-env",
"/nix/store/b5pfwxq3zlbg0403ngr3h39jr42ys521-python3.6-pycodestyle-2.4.0",
"/nix/store/yhk6i2daplybp34ff5zlrfh341ykmap9-python3.6-mccabe-0.6.1",
"/nix/store/z1c96zgjwm1dlil3h53yy0cyxh6g6k8h-python3.6-pyflakes-2.0.0"
],
"/nix/store/gsgdj34vv5hh3iyyfm7yh69j6dq0br9q-openssl-1.0.2p": [
"/nix/store/gsgdj34vv5hh3iyyfm7yh69j6dq0br9q-openssl-1.0.2p"
],
"/nix/store/wwhp4klykgvd7xwl94izc8xxb9idf4wy-bzip2-1.0.6.0.1": [
"/nix/store/wwhp4klykgvd7xwl94izc8xxb9idf4wy-bzip2-1.0.6.0.1"
]
}
#!/usr/bin/env python
import argparse
import json
import sys
argparser = argparse.ArgumentParser()
argparser.add_argument(
'--graph', type=argparse.FileType('r', encoding='UTF-8'),
required=True)
argparser.add_argument(
'--cuts', type=argparse.FileType('r', encoding='UTF-8'),
required=True)
def get_layer(graph, key, cut_points, _layer=None):
if _layer is None:
_layer = set()
node = graph[key]
_layer.add(key)
for ref in node.get('references', []):
if ref == key or ref in cut_points:
continue
get_layer(graph, ref, cut_points, _layer=_layer)
return _layer
def process_layers(graph_data, cut_points):
leaf_path = graph_data['exportReferencesGraph']['graph']
graph = {
node['path']: node
for node in graph_data['graph']
}
layer_keys = cut_points.intersection(set(graph.keys()))
layer_keys.add(leaf_path)
return {
layer_key: get_layer(graph, layer_key, cut_points)
for layer_key in layer_keys
}
def find_duplicate_refs(layers):
dups = set()
for layer_key, layer in layers.items():
for l_k, l in layers.items():
if layer_key == l_k:
continue
dups.update(l.intersection(layer))
return dups
class SetJSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, set):
return sorted(obj)
return json.JSONEncoder.default(self, obj)
if __name__ == '__main__':
args = argparser.parse_args()
graph_data = json.load(args.graph)
cut_points = set(json.load(args.cuts))
layers = process_layers(graph_data, cut_points)
for dup in find_duplicate_refs(layers):
sys.stderr.write(
'Found path in multiple layers, consider adding cut: %s\n' % dup)
print(json.dumps(layers, cls=SetJSONEncoder, indent=2))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment