Skip to content

Commit

Permalink
Add apk support (alpine)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielbraun89 authored Aug 22, 2023
1 parent a79cd67 commit ced93c0
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 0 deletions.
10 changes: 10 additions & 0 deletions nanolayer/cli/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import typer

from nanolayer.installers.apk.apk_installer import ApkInstaller
from nanolayer.installers.apt.apt_installer import AptInstaller
from nanolayer.installers.apt_get.apt_get_installer import AptGetInstaller
from nanolayer.installers.aptitude.aptitude_installer import AptitudeInstaller
Expand Down Expand Up @@ -121,6 +122,15 @@ def install_aptitude_packages(
)


@app.command("apk")
def install_apk_packages(
packages: str = typer.Argument(None, help="comma separated list of apk packages")
) -> None:
ApkInstaller.install(
packages=packages.split(","),
)


@app.command("gh-release")
def install_gh_release_binary(
repo: str,
Expand Down
Empty file.
40 changes: 40 additions & 0 deletions nanolayer/installers/apk/apk_installer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import tempfile
from typing import List

from nanolayer.utils.invoker import Invoker
from nanolayer.utils.linux_information_desk import LinuxInformationDesk


class ApkInstaller:
@classmethod
def is_alpine(cls) -> bool:
return (
LinuxInformationDesk.get_release_id()
== LinuxInformationDesk.LinuxReleaseID.alpine
)

@classmethod
def delete(cls, packages: List[str]) -> None:
assert cls.is_alpine(), "apk should be used on alpine linux distribution"
Invoker.invoke(command=f"apk del {' '.join(packages)}")

@classmethod
def install(
cls,
packages: List[str],
) -> None:
assert cls.is_alpine(), "apk should be used on alpine linux distribution"

with tempfile.TemporaryDirectory() as tempdir:
Invoker.invoke(command=f"cp -p -R /var/cache/apk {tempdir}")

try:
Invoker.invoke(command="apk update")

Invoker.invoke(command=f"apk add --no-cache {' '.join(packages)}")

finally:
# Note: not using dir/* syntax as that doesnt work on 'sh' shell (alpine)
Invoker.invoke(
command=f"rm -r /var/cache/apk && mv {tempdir}/apk /var/cache/apk"
)
21 changes: 21 additions & 0 deletions nanolayer/installers/devcontainer_feature/oci_feature_installer.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import distutils
import logging
import os
import pwd
Expand All @@ -6,6 +7,7 @@
from pathlib import Path
from typing import Dict, Optional, Union

from nanolayer.installers.apk.apk_installer import ApkInstaller
from nanolayer.installers.devcontainer_feature.models.devcontainer_feature import (
Feature,
)
Expand All @@ -27,6 +29,9 @@ class OCIFeatureInstaller:
class NoPremissions(PermissionError):
pass

class OCIFeatureInstallerError(Exception):
pass

_ORDERED_BASE_REMOTE_USERS = ("vscode", "node", "codespace")
_FALLBACK_USER_ID_A = (
1000 # user 1000 (mostly the base user of the contianer eg. "ubuntu" etc)
Expand Down Expand Up @@ -128,8 +133,24 @@ def install(

command += f"./{cls._FEATURE_ENTRYPOINT}"

# ensure existance of bash in order to succesfully run the command
bash_installed = False
if distutils.spawn.find_executable("bash") is None:
if ApkInstaller.is_alpine():
ApkInstaller.install(packages=["bash"])
bash_installed = True
else:
raise cls.OCIFeatureInstallerError(
"no bash detected. please make sure bash is installed"
)

Invoker.invoke(command)

# now that its no longer needed we remove bash if it was installed by us
if bash_installed:
if ApkInstaller.is_alpine():
ApkInstaller.delete(packages=["bash"])

cls._set_envs(feature_obj)

if invoke_entrypoint and feature_obj.entrypoint is not None:
Expand Down

0 comments on commit ced93c0

Please sign in to comment.