mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-10 18:56:30 +00:00
Add support for addon config.
This commit is contained in:
parent
f127de8059
commit
530f17d502
@ -1,13 +1,31 @@
|
||||
"""Init file for HassIO addons."""
|
||||
import logging
|
||||
|
||||
from .config import AddonsConfig
|
||||
from .git import AddonsRepo
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AddonManager(object):
|
||||
class AddonsManager(object):
|
||||
"""Manage addons inside HassIO."""
|
||||
|
||||
def __init__(self, config, loop):
|
||||
"""Initialize docker base wrapper."""
|
||||
self.config = config
|
||||
self.loop = loop
|
||||
self.repo = AddonsRepo(config, loop)
|
||||
self.addons = AddonsConfig(config)
|
||||
self.dockers = {}
|
||||
|
||||
async def prepare(self):
|
||||
"""Startup addon management."""
|
||||
# load addon repository
|
||||
if await self.repo.load():
|
||||
self.addons.read_addons_repo()
|
||||
|
||||
async def relaod_addons(self):
|
||||
"""Update addons from repo and reload list."""
|
||||
if not await self.repo.pull():
|
||||
return
|
||||
self.addons.read_addons_repo()
|
||||
|
62
hassio/addons/config.py
Normal file
62
hassio/addons/config.py
Normal file
@ -0,0 +1,62 @@
|
||||
"""Init file for HassIO addons."""
|
||||
import logging
|
||||
import glob
|
||||
import json
|
||||
|
||||
import voluptuous as vol
|
||||
from voluptuous.humanize import humanize_error
|
||||
|
||||
from ..const import (
|
||||
FILE_HASSIO_ADDONS, ATTR_NAME, ATTR_VERSION, ATTR_SLUG, ATTR_DESCRIPTON,
|
||||
ATTR_STARTUP, ATTR_BOOT, ATTR_MAP_SSL, ATTR_MAP_CONFIG, ATTR_MAP_DATA,
|
||||
ATTR_OPTIONS, STARTUP_ONCE, STARTUP_AFTER, STARTUP_BEFORE, BOOT_START,
|
||||
BOOT_STOP, BOOT_MANUAL)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ADDONS_REPO_PATTERN = "{}/*/config.json"
|
||||
|
||||
# pylint: disable=no-value-for-parameter
|
||||
SCHEMA_ADDON_CONFIG = vol.Schema({
|
||||
vol.Required(ATTR_NAME): vol.Coerce(str),
|
||||
vol.Required(ATTR_VERSION): vol.Coerce(str),
|
||||
vol.Required(ATTR_SLUG): vol.Coerce(str),
|
||||
vol.Required(ATTR_DESCRIPTON): vol.Coerce(str),
|
||||
vol.Required(ATTR_STARTUP):
|
||||
vol.In([STARTUP_BEFORE, STARTUP_AFTER, STARTUP_ONCE]),
|
||||
vol.Required(ATTR_BOOT):
|
||||
vol.IN([BOOT_START, BOOT_STOP, BOOT_MANUAL]),
|
||||
vol.Required(ATTR_MAP_CONFIG): vol.Boolean(),
|
||||
vol.Required(ATTR_MAP_SSL): vol.Boolean(),
|
||||
vol.Required(ATTR_MAP_DATA): vol.Boolean(),
|
||||
vol.Required(ATTR_OPTIONS): dict,
|
||||
})
|
||||
|
||||
|
||||
class AddonsConfig(Config):
|
||||
"""Config for addons inside HassIO."""
|
||||
|
||||
def __init__(self, config):
|
||||
"""Initialize docker base wrapper."""
|
||||
super().__init__(FILE_HASSIO_ADDONS)
|
||||
self.config
|
||||
self._addons_data = {}
|
||||
|
||||
def read_addons_repo(self):
|
||||
"""Read data from addons repository."""
|
||||
pattern = ADDONS_REPO_PATTERN.format(self.config.path_addons_repo)
|
||||
|
||||
for addon in glob.iglob(pattern):
|
||||
try:
|
||||
with open(addon, 'r') as cfile:
|
||||
addon_config = json.loads(cfile.read())
|
||||
|
||||
addon_config = SCHEMA_ADDON_CONFIG(addon_config)
|
||||
self._addons_data[addon_config[ATTR_SLUG]] = addon_config
|
||||
|
||||
except (OSError, KeyError):
|
||||
_LOGGER.warning("Can't read %s", addon)
|
||||
|
||||
except vol.Invalid as ex:
|
||||
_LOGGER.warnign("Can't read %s -> %s.", addon,
|
||||
humanize_error(addon_config, ex))
|
@ -20,7 +20,7 @@ class AddonsRepo(object):
|
||||
self.repo = None
|
||||
self._lock = asyncio.Lock(loop=loop)
|
||||
|
||||
async def init(self):
|
||||
async def load(self):
|
||||
"""Init git addon repo."""
|
||||
if not os.path.isdir(self.config.path_addons_repo):
|
||||
return await self.clone()
|
||||
@ -32,6 +32,9 @@ class AddonsRepo(object):
|
||||
|
||||
except (git.InvalidGitRepositoryError, git.NoSuchPathError) as err:
|
||||
_LOGGER.error("Can't load addons repo: %s.", err)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
async def clone(self):
|
||||
"""Clone git addon repo."""
|
||||
@ -43,12 +46,15 @@ class AddonsRepo(object):
|
||||
|
||||
except (git.InvalidGitRepositoryError, git.NoSuchPathError) as err:
|
||||
_LOGGER.error("Can't clone addons repo: %s.", err)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
async def pull(self):
|
||||
"""Pull git addon repo."""
|
||||
if self._lock.locked():
|
||||
_LOGGER.warning("It is already a task in progress.")
|
||||
return
|
||||
return False
|
||||
|
||||
await with self._lock:
|
||||
try:
|
||||
@ -57,3 +63,6 @@ class AddonsRepo(object):
|
||||
|
||||
except (git.InvalidGitRepositoryError, git.NoSuchPathError) as err:
|
||||
_LOGGER.error("Can't pull addons repo: %s.", err)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
@ -82,7 +82,7 @@ async def api_validate(schema, request):
|
||||
"""Validate request data with schema."""
|
||||
data = await request.json(loads=json_loads)
|
||||
try:
|
||||
schema(data)
|
||||
data = schema(data)
|
||||
except vol.Invalid as ex:
|
||||
raise RuntimeError(humanize_error(data, ex)) from None
|
||||
|
||||
|
@ -21,12 +21,11 @@ ADDONS_DATA = "{}/addons_data"
|
||||
UPSTREAM_BETA = 'upstream_beta'
|
||||
|
||||
|
||||
class CoreConfig(object):
|
||||
class Config(object):
|
||||
"""Hold all config data."""
|
||||
|
||||
def __init__(self, websession, config_file=FILE_HASSIO_CONFIG):
|
||||
def __init__(self, config_file):
|
||||
"""Initialize config object."""
|
||||
self.websession = websession
|
||||
self._filename = config_file
|
||||
self._data = {}
|
||||
|
||||
@ -38,14 +37,6 @@ class CoreConfig(object):
|
||||
except OSError:
|
||||
_LOGGER.warning("Can't read %s", self._filename)
|
||||
|
||||
# init data
|
||||
if not self._data:
|
||||
self._data.update({
|
||||
HOMEASSISTANT_IMAGE: os.environ['HOMEASSISTANT_REPOSITORY'],
|
||||
UPSTREAM_BETA: False,
|
||||
})
|
||||
self.save()
|
||||
|
||||
def save(self):
|
||||
"""Store data to config file."""
|
||||
try:
|
||||
@ -57,6 +48,24 @@ class CoreConfig(object):
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class CoreConfig(Config):
|
||||
"""Hold all core config data."""
|
||||
|
||||
def __init__(self, websession):
|
||||
"""Initialize config object."""
|
||||
self.websession = websession
|
||||
|
||||
super().__ini__(FILE_HASSIO_CONFIG)
|
||||
|
||||
# init data
|
||||
if not self._data:
|
||||
self._data.update({
|
||||
HOMEASSISTANT_IMAGE: os.environ['HOMEASSISTANT_REPOSITORY'],
|
||||
UPSTREAM_BETA: False,
|
||||
})
|
||||
self.save()
|
||||
|
||||
async def fetch_update_infos(self):
|
||||
"""Read current versions from web."""
|
||||
current = await fetch_current_versions(
|
||||
|
@ -28,3 +28,21 @@ RESULT_OK = 'ok'
|
||||
ATTR_VERSION = 'version'
|
||||
ATTR_CURRENT = 'current'
|
||||
ATTR_BETA = 'beta'
|
||||
ATTR_NAME = 'name'
|
||||
ATTR_SLUG = 'slug'
|
||||
ATTR_DESCRIPTON = 'description'
|
||||
ATTR_STARTUP = 'startup'
|
||||
ATTR_BOOT = 'boot'
|
||||
ATTR_PORTS = 'ports'
|
||||
ATTR_MAP_CONFIG = 'map_config'
|
||||
ATTR_MAP_SSL = 'map_ssl'
|
||||
ATTR_MAP_DATA = 'map_data'
|
||||
ATTR_OPTIONS = 'options'
|
||||
ATTR_INSTALLED = 'installed'
|
||||
|
||||
STARTUP_BEFORE = 'before'
|
||||
STARTUP_AFTER = 'after'
|
||||
STARTUP_ONCE = 'once'
|
||||
BOOT_START = 'start'
|
||||
BOOT_STOP = 'stop'
|
||||
BOOT_MANUAL = 'manual'
|
||||
|
Loading…
x
Reference in New Issue
Block a user