Skip to content

Commit

Permalink
Port import-lxc to bash (#169)
Browse files Browse the repository at this point in the history
  • Loading branch information
ihucos committed Feb 7, 2020
1 parent 09a4a3a commit c9176b2
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 170 deletions.
169 changes: 29 additions & 140 deletions exec/import-lxc
@@ -1,151 +1,40 @@
#!/usr/bin/env python3
#!/bin/bash
#
# usage: plash import-lxc IMAGE-NAME [--dry]
# Import image from linuxcontainers.org
# usage: plash import-lxc DISTRIBUTION:RELEASE [--dry]
# Import an image from https://images.linuxcontainers.org/
# if --dry is set, the image url is printed but not imported

import re
import os
import sys
from urllib.error import URLError
from urllib.request import urlopen
set -e
set -o pipefail

from plash import utils
HOME_URL=https://images.linuxcontainers.org
INDEX_URL=https://images.linuxcontainers.org/meta/1.0/index-user
ARCH=amd64

LXC_URL_TEMPL = "https://images.linuxcontainers.org/images/{}/{}/{}/{}/{}/rootfs.tar.xz"
if [ -z "$1" ]; then
echo "usage: plash import-lxc DISTRIBUTION:RELEASE [--dry]" >&2
exit 1
fi

UBUNTU_ABC = "tuvwxyzabcdefghijklmnopqrs" # rotate manually every decade or so
if ! [[ "$1" = *':'* ]]; then
echo "plash error: also specify the release, example: deian:sid" >&2
exit 1
fi

DEPRECTATED_IMAGE_NAMES = {
# 'plamo': ... 'plamo' is really forgotten for
"cosmic": "ubuntu:cosmic",
"disco": "ubuntu:disco",
"edge": "alpine:edge",
"eoan": "ubuntu:eoan",
"jessie": "debian:jessie",
"sid": "debian:sid",
"stretch": "debian:stretch",
"trusty": "ubuntu:trusty",
"tumbleweed": "opensuse:tumbleweed",
"xenial": "ubuntu:xenial",
}


def use_current(version):
return int(version == "current")


def use_version_number(version):
try:
return tuple(int(i) for i in version.split("."))
except ValueError:
return (-1,)


def use_index(order):
order_lower = [i.lower() for i in order]

def quantifier(version):
try:
return order_lower.index(version.lower())
except ValueError:
return -1

return quantifier


def use_alphabet(version):
return version


def use_ubuntu(version):
return UBUNTU_ABC.find(version[0].lower())


USE_NEWEST_VERSION = {
"alpine": use_version_number,
"archlinux": use_current,
"centos": use_version_number,
"debian": use_index(["jessie", "stretch", "buster", "bullseye"]),
"devuan": use_alphabet,
"fedora": use_version_number,
"gentoo": use_current,
"kali": use_current,
"opensuse": use_version_number,
"openwrt": use_current,
"oracle": use_version_number,
"sabayon": use_current,
"ubuntu": use_ubuntu,
"ubuntu-core": use_version_number,
}

utils.assert_initialized()

try:
image_name = sys.argv[1]
dry_run = sys.argv[2:3] == ["--dry"]
except IndexError:
utils.die_with_usage()

with utils.catch_and_die([URLError]):
content = urlopen("https://images.linuxcontainers.org/").read().decode()
matches = re.findall(
"<tr><td>(.+?)</td><td>(.+?)</td><td>(.+?)</td><td>(.+?)</td><td>(.+?)</td><td>(.+?)</td><td>(.+?)</td><td>(.+?)</td></tr>",
content,
match=$(curl --silent --fail --location $INDEX_URL |
awk -F";" '$3 == "'"$ARCH"'" && $4 == "default" { print $1":"$2" "$6 }' |
awk -v a="$1" 'a == $1 { print $2 }'
)

versions = {}
urls = {}
for distro, version, arch, variant, date, _, _, _ in matches:
if variant != "default" or arch != "amd64":
continue
url = LXC_URL_TEMPL.format(distro, version, arch, variant, date)
urls[(distro, version)] = url
versions.setdefault(distro, [])
versions[distro].append(version)


def die_image_not_found():
all_images = sorted([":".join(i) for i in urls] + list(USE_NEWEST_VERSION.keys()))
utils.die(
"image not found ({}), but there is: {}".format(
repr(image_name), " ".join(all_images)
)
)


# handle eventual deprecated image
try:
orig_image_name = image_name
image_name = DEPRECTATED_IMAGE_NAMES[image_name]
print(
"plash: rename image (due to indefinitely supported deprecation): {} -> {}".format(
orig_image_name, image_name
),
file=sys.stderr,
)
except KeyError:
pass

if not ":" in image_name:
try:
version_quantifier = USE_NEWEST_VERSION[image_name]
except KeyError:
die_image_not_found()

sorted_versions = sorted(versions[image_name], key=version_quantifier)
latest_version = list(sorted_versions)[-1]
image_key = (image_name, latest_version)
else:
image_key = tuple(image_name.split(":"))
if [ -z "$match" ]; then
echo "plash error: \"$1\" not listed in $HOME_URL/" >&2
exit 1
fi

try:
url = urls[image_key]
except KeyError:
die_image_not_found()
rootfs="${HOME_URL}${match}"rootfs.tar.xz

signature_url = "{}.asc".format(url)
if dry_run:
print(url)
else:
utils.plash_exec("import-url", url, signature_url)
if [[ "$2" = "--dry" ]]; then
echo "$rootfs"
else
exec plash import-url "$rootfs" "$rootfs".asc
fi
17 changes: 10 additions & 7 deletions lib/python/plash/macros/shortcuts.py
Expand Up @@ -4,13 +4,16 @@
x=[["run"]],
l=[["layer"]],
f=[["from"]],
A=[["from", "alpine"], ["apk"]],
U=[["from", "ubuntu"], ["apt"]],
F=[["from", "fedora"], ["dnf"]],
D=[["from", "debian"], ["apt"]],
C=[["from", "centos"], ["yum"]],
R=[["from", "archlinux"], ["pacman"]],
G=[["from", "gentoo"], ["emerge"]],

# pin down whatever will last the longest like that in the source
# code
A=[["from", "alpine:edge"], ["apk"]],
U=[["from", "ubuntu:bionic"], ["apt"]],
F=[["from", "fedora:31"], ["dnf"]],
D=[["from", "debian:sid"], ["apt"]],
C=[["from", "centos:8"], ["yum"]],
R=[["from", "archlinux:current"], ["pacman"]],
G=[["from", "gentoo:current"], ["emerge"]],
)

for name, macro in ALIASES.items():
Expand Down
26 changes: 4 additions & 22 deletions tests/command/import-lxc
Expand Up @@ -14,27 +14,9 @@ plash run $cont ls
(! plash import-lxc unknownos --dry)

: dry import returns https url
plash import-lxc alpine --dry | grep '^https://'
plash import-lxc alpine:edge --dry | grep '^https://'

: Some images give a tar file
test_import_lxc alpine
test_import_lxc archlinux
test_import_lxc centos
test_import_lxc debian
test_import_lxc devuan
test_import_lxc fedora
test_import_lxc gentoo
test_import_lxc kali
test_import_lxc opensuse
test_import_lxc openwrt
test_import_lxc oracle
test_import_lxc sabayon
test_import_lxc ubuntu
test_import_lxc ubuntu-core

: dry import deprecated image succeeds
plash import-lxc trusty --dry

: dry import with version prefix succeeds
plash import-lxc ubuntu:cosmic --dry
plash import-lxc archlinux:current --dry
test_import_lxc alpine:edge
test_import_lxc archlinux:current
test_import_lxc debian:sid
11 changes: 10 additions & 1 deletion tests/macro/shortcuts
@@ -1,4 +1,13 @@
#!/bin/sh
: test only one shortuct
: test the x shortuct
out=$(plash eval -x hi)
test "$out" = hi

: test pinned down version in shortcuts
plash import-lxc alpine:edge --dry
plash import-lxc ubuntu:bionic --dry
plash import-lxc fedora:31 --dry
plash import-lxc debian:sid --dry
plash import-lxc centos:8 --dry
plash import-lxc archlinux:current --dry
plash import-lxc gentoo:current --dry

0 comments on commit c9176b2

Please sign in to comment.