Compare commits

..

4 Commits

Author SHA1 Message Date
Pascal Vizeli
e27337da85 Improve local build / allow cache on dev (#2810) 2021-04-15 08:19:58 +02:00
dependabot[bot]
8f22316869 Bump colorlog from 4.8.0 to 5.0.1 (#2808)
Bumps [colorlog](https://github.com/borntyping/python-colorlog) from 4.8.0 to 5.0.1.
- [Release notes](https://github.com/borntyping/python-colorlog/releases)
- [Commits](https://github.com/borntyping/python-colorlog/compare/v4.8.0...v5.0.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-04-14 17:01:27 +02:00
Joakim Sørensen
dd10d3e037 Guard against multiple client creations (#2809) 2021-04-14 14:30:49 +02:00
dependabot[bot]
4a53c62af8 Bump home-assistant/builder from 2021.04.0 to 2021.04.1 (#2807)
Bumps [home-assistant/builder](https://github.com/home-assistant/builder) from 2021.04.0 to 2021.04.1.
- [Release notes](https://github.com/home-assistant/builder/releases)
- [Commits](https://github.com/home-assistant/builder/compare/2021.04.0...b77028ab08315dd69807752d2f3e00b0f0f49786)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-04-14 14:30:31 +02:00
9 changed files with 39 additions and 116 deletions

View File

@@ -127,7 +127,7 @@ jobs:
run: echo "BUILD_ARGS=--test" >> $GITHUB_ENV run: echo "BUILD_ARGS=--test" >> $GITHUB_ENV
- name: Build supervisor - name: Build supervisor
uses: home-assistant/builder@2021.04.0 uses: home-assistant/builder@2021.04.1
with: with:
args: | args: |
$BUILD_ARGS \ $BUILD_ARGS \
@@ -198,7 +198,7 @@ jobs:
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Build the Supervisor - name: Build the Supervisor
uses: home-assistant/builder@2021.04.0 uses: home-assistant/builder@2021.04.1
with: with:
args: | args: |
--test \ --test \

View File

@@ -5,7 +5,7 @@ attrs==20.3.0
awesomeversion==21.4.0 awesomeversion==21.4.0
brotli==1.0.9 brotli==1.0.9
cchardet==2.1.7 cchardet==2.1.7
colorlog==4.8.0 colorlog==5.0.1
cpe==1.2.1 cpe==1.2.1
cryptography==3.4.6 cryptography==3.4.6
debugpy==1.2.1 debugpy==1.2.1

View File

@@ -9,6 +9,7 @@ from awesomeversion import AwesomeVersion
from ..const import ( from ..const import (
ATTR_ARGS, ATTR_ARGS,
ATTR_BUILD_FROM, ATTR_BUILD_FROM,
ATTR_LABELS,
ATTR_SQUASH, ATTR_SQUASH,
FILE_SUFFIX_CONFIGURATION, FILE_SUFFIX_CONFIGURATION,
META_ADDON, META_ADDON,
@@ -46,9 +47,12 @@ class AddonBuild(FileConfiguration, CoreSysAttributes):
@property @property
def base_image(self) -> str: def base_image(self) -> str:
"""Return base image for this add-on.""" """Return base image for this add-on."""
return self._data[ATTR_BUILD_FROM].get( if not self._data[ATTR_BUILD_FROM]:
self.sys_arch.default, f"homeassistant/{self.sys_arch.default}-base:latest" return f"homeassistant/{self.sys_arch.default}-base:latest"
)
# Evaluate correct base image
arch = self.sys_arch.match(list(self._data[ATTR_BUILD_FROM].keys()))
return self._data[ATTR_BUILD_FROM][arch]
@property @property
def squash(self) -> bool: def squash(self) -> bool:
@@ -60,6 +64,11 @@ class AddonBuild(FileConfiguration, CoreSysAttributes):
"""Return additional Docker build arguments.""" """Return additional Docker build arguments."""
return self._data[ATTR_ARGS] return self._data[ATTR_ARGS]
@property
def additional_labels(self) -> Dict[str, str]:
"""Return additional Docker labels."""
return self._data[ATTR_LABELS]
@property @property
def is_valid(self) -> bool: def is_valid(self) -> bool:
"""Return true if the build env is valid.""" """Return true if the build env is valid."""
@@ -76,7 +85,7 @@ class AddonBuild(FileConfiguration, CoreSysAttributes):
"path": str(self.addon.path_location), "path": str(self.addon.path_location),
"tag": f"{self.addon.image}:{version!s}", "tag": f"{self.addon.image}:{version!s}",
"pull": True, "pull": True,
"forcerm": True, "forcerm": not self.sys_dev,
"squash": self.squash, "squash": self.squash,
"labels": { "labels": {
"io.hass.version": version, "io.hass.version": version,
@@ -84,6 +93,7 @@ class AddonBuild(FileConfiguration, CoreSysAttributes):
"io.hass.type": META_ADDON, "io.hass.type": META_ADDON,
"io.hass.name": self._fix_label("name"), "io.hass.name": self._fix_label("name"),
"io.hass.description": self._fix_label("description"), "io.hass.description": self._fix_label("description"),
**self.additional_labels,
}, },
"buildargs": { "buildargs": {
"BUILD_FROM": self.base_image, "BUILD_FROM": self.base_image,

View File

@@ -47,6 +47,7 @@ from ..const import (
ATTR_INIT, ATTR_INIT,
ATTR_JOURNALD, ATTR_JOURNALD,
ATTR_KERNEL_MODULES, ATTR_KERNEL_MODULES,
ATTR_LABELS,
ATTR_LEGACY, ATTR_LEGACY,
ATTR_LOCATON, ATTR_LOCATON,
ATTR_MACHINE, ATTR_MACHINE,
@@ -317,9 +318,8 @@ SCHEMA_BUILD_CONFIG = vol.Schema(
{vol.In(ARCH_ALL): vol.Match(RE_DOCKER_IMAGE_BUILD)} {vol.In(ARCH_ALL): vol.Match(RE_DOCKER_IMAGE_BUILD)}
), ),
vol.Optional(ATTR_SQUASH, default=False): vol.Boolean(), vol.Optional(ATTR_SQUASH, default=False): vol.Boolean(),
vol.Optional(ATTR_ARGS, default=dict): vol.Schema( vol.Optional(ATTR_ARGS, default=dict): vol.Schema({str: str}),
{vol.Coerce(str): vol.Coerce(str)} vol.Optional(ATTR_LABELS, default=dict): vol.Schema({str: str}),
),
}, },
extra=vol.REMOVE_EXTRA, extra=vol.REMOVE_EXTRA,
) )

View File

@@ -102,6 +102,7 @@ ATTR_APPARMOR = "apparmor"
ATTR_APPLICATION = "application" ATTR_APPLICATION = "application"
ATTR_ARCH = "arch" ATTR_ARCH = "arch"
ATTR_ARGS = "args" ATTR_ARGS = "args"
ATTR_LABELS = "labels"
ATTR_AUDIO = "audio" ATTR_AUDIO = "audio"
ATTR_AUDIO_INPUT = "audio_input" ATTR_AUDIO_INPUT = "audio_input"
ATTR_AUDIO_OUTPUT = "audio_output" ATTR_AUDIO_OUTPUT = "audio_output"

View File

@@ -86,17 +86,22 @@ class HomeAssistantWebSocket(CoreSysAttributes):
"""Initialize Home Assistant object.""" """Initialize Home Assistant object."""
self.coresys: CoreSys = coresys self.coresys: CoreSys = coresys
self._client: Optional[WSClient] = None self._client: Optional[WSClient] = None
self._lock: asyncio.Lock = asyncio.Lock()
async def _get_ws_client(self) -> WSClient: async def _get_ws_client(self) -> WSClient:
"""Return a websocket client.""" """Return a websocket client."""
await self.sys_homeassistant.api.ensure_access_token() async with self._lock:
client = await WSClient.connect_with_auth( if self._client is not None:
self.sys_websession_ssl, return self._client
f"{self.sys_homeassistant.api_url}/api/websocket",
self.sys_homeassistant.api.access_token,
)
return client await self.sys_homeassistant.api.ensure_access_token()
client = await WSClient.connect_with_auth(
self.sys_websession_ssl,
f"{self.sys_homeassistant.api_url}/api/websocket",
self.sys_homeassistant.api.access_token,
)
return client
async def async_send_command(self, message: Dict[str, Any]): async def async_send_command(self, message: Dict[str, Any]):
"""Send a command with the WS client.""" """Send a command with the WS client."""

View File

@@ -1,8 +1,6 @@
"""Supervisor job manager.""" """Supervisor job manager."""
from contextvars import ContextVar
import logging import logging
from typing import Dict, List, Optional from typing import Dict, List, Optional
from uuid import uuid4
from ..coresys import CoreSys, CoreSysAttributes from ..coresys import CoreSys, CoreSysAttributes
from ..utils.common import FileConfiguration from ..utils.common import FileConfiguration
@@ -10,48 +8,17 @@ from .const import ATTR_IGNORE_CONDITIONS, FILE_CONFIG_JOBS, JobCondition
from .validate import SCHEMA_JOBS_CONFIG from .validate import SCHEMA_JOBS_CONFIG
_LOGGER: logging.Logger = logging.getLogger(__package__) _LOGGER: logging.Logger = logging.getLogger(__package__)
CONTEXT = ContextVar("id")
class SupervisorJob(CoreSysAttributes): class SupervisorJob(CoreSysAttributes):
"""Supervisor running job class.""" """Supervisor running job class."""
def __init__( def __init__(self, coresys: CoreSys, name: str):
self,
coresys: CoreSys,
name: Optional[str] = None,
parrent_id: Optional[str] = None,
):
"""Initialize the JobManager class.""" """Initialize the JobManager class."""
self.coresys: CoreSys = coresys self.coresys: CoreSys = coresys
self._name: Optional[str] = name self.name: str = name
self._parrent_id: Optional[str] = parrent_id
self._progress: int = 0 self._progress: int = 0
self._stage: Optional[str] = None self._stage: Optional[str] = None
self._data: Optional[dict] = None
self._id = (
self.sys_jobs.context.get() if self.parrent_id is None else uuid4().hex
)
@property
def id(self) -> str:
"""Return the ID for the job."""
return self._id
@property
def parrent_id(self) -> Optional[str]:
"""Return the ID for the parrent job."""
return self._parrent_id
@property
def name(self) -> str:
"""Return the name for the job."""
return self._name or self.id
@name.setter
def name(self, value: str) -> None:
"""Set the name of a job."""
self._name = value
@property @property
def progress(self) -> int: def progress(self) -> int:
@@ -63,33 +30,22 @@ class SupervisorJob(CoreSysAttributes):
"""Return the current stage.""" """Return the current stage."""
return self._stage return self._stage
@property
def data(self) -> Optional[str]:
"""Return additional data for the job."""
return self._data
def update( def update(
self, self, progress: Optional[int] = None, stage: Optional[str] = None
progress: Optional[int] = None,
stage: Optional[str] = None,
data: Optional[dict] = None,
) -> None: ) -> None:
"""Update the job object.""" """Update the job object."""
if progress is not None: if progress is not None:
if progress >= round(100) and self.parrent_id is None: if progress >= round(100):
self.sys_jobs.remove_job(self) self.sys_jobs.remove_job(self)
return return
self._progress = round(progress) self._progress = round(progress)
if stage is not None: if stage is not None:
self._stage = stage self._stage = stage
if data is not None:
self._data = data
_LOGGER.debug( _LOGGER.debug(
'Update: {"name": %s, "progress": %s, "stage": %s, "data": %s}', "Job updated; name: %s, progress: %s, stage: %s",
self.name, self.name,
self.progress, self.progress,
self.stage, self.stage,
self.data,
) )
@@ -100,7 +56,6 @@ class JobManager(FileConfiguration, CoreSysAttributes):
"""Initialize the JobManager class.""" """Initialize the JobManager class."""
super().__init__(FILE_CONFIG_JOBS, SCHEMA_JOBS_CONFIG) super().__init__(FILE_CONFIG_JOBS, SCHEMA_JOBS_CONFIG)
self.coresys: CoreSys = coresys self.coresys: CoreSys = coresys
self.context = CONTEXT
self._jobs: Dict[str, SupervisorJob] = {} self._jobs: Dict[str, SupervisorJob] = {}
@property @property
@@ -113,21 +68,6 @@ class JobManager(FileConfiguration, CoreSysAttributes):
"""Return a list of ingore condition.""" """Return a list of ingore condition."""
return self._data[ATTR_IGNORE_CONDITIONS] return self._data[ATTR_IGNORE_CONDITIONS]
@property
def job(self) -> SupervisorJob:
"""Return the current job based on context ID."""
try:
self.context.get()
except LookupError:
self.context.set(uuid4().hex)
context = self.context.get()
if context not in self._jobs:
self._jobs[context] = SupervisorJob(self.coresys)
return self._jobs[context]
@ignore_conditions.setter @ignore_conditions.setter
def ignore_conditions(self, value: List[JobCondition]) -> None: def ignore_conditions(self, value: List[JobCondition]) -> None:
"""Set a list of ignored condition.""" """Set a list of ignored condition."""

View File

@@ -72,7 +72,7 @@ class Job(CoreSysAttributes):
"""Wrap the method.""" """Wrap the method."""
self._post_init(args) self._post_init(args)
job = self.coresys.jobs.job job = self.sys_jobs.get_job(self.name)
# Handle condition # Handle condition
if self.conditions: if self.conditions:

View File

@@ -1,33 +0,0 @@
"""Test the job context vars."""
from supervisor.coresys import CoreSys
from supervisor.jobs.decorator import Job
async def test_job_context(coresys: CoreSys):
"""Test the job context."""
class TestClass:
"""Test class."""
def __init__(self, coresys: CoreSys):
"""Initialize the test class."""
self.coresys = coresys
self.jobid = str(self.coresys.jobs.job.id)
@Job()
async def first(self):
"""Execute the class method."""
await self.second()
return True
@Job()
async def second(self):
"""Execute the class method."""
return True
test = TestClass(coresys)
await test.first()
assert test.jobid == coresys.jobs.job.id
await test.second()
assert test.jobid == coresys.jobs.job.id