YOGYUI

Home Assistant 애드온 컨테이너 내부에서 애드온 옵션 변경하기 (bashio) 본문

홈네트워크(IoT)/일반

Home Assistant 애드온 컨테이너 내부에서 애드온 옵션 변경하기 (bashio)

요겨 2024. 3. 20. 16:17
반응형

Home Assistant: Modify add-on option value from inside add-on container using Bashio

홈어시스턴트(Home Assistant, HA)의 애드온 개발 시 실행 인자를 도입해야 하는 경우가 대다수인데, 컨테이너 내부에서 해당 옵션 값을 바꾸려면 HA의 Supervisor API를 사용해야 한다 (HTTP POST 리퀘스트)

 

만약 Supervisor API 호출에 대한 별도의 개발을 하고 싶지 않다면, bashio 애드온의 wrapper 함수를 활용하면 손쉽게 해결할 수 있다

https://developers.home-assistant.io/docs/add-ons/configuration

 

bashio는 HA 애드온 시 사용하는 베이스 이미지들에 기본적으로 설치된 애드온이라 베이스 이미지를 애드온 도커 빌드 시 FROM으로 사용할 경우 별도의 설치과정 없이 사용해도 된다

https://github.com/hassio-addons/bashio

 

쉘에서의 bashio 함수 호출 원형은 다음과 같다

$(bashio::addon.option '<option key>' [<value>])
  • <option key>: 설정하고자 하는 옵션 딕셔너리 키 (key) 
  • <value>: 설정하고자 하는 옵션 딕셔너리 밸류 (value)
                   만약 아무값도 입력하지 않으면 옵션이 삭제된다

실제 활용법을 봐야 어떤 식으로 사용할 지 감이 잡히므로, 간단하게 예를 살펴보자

 

애드온의 config.yaml에 다음과 같이 options 항목을 구현해뒀다고 하자

[config.yaml]

options:
  value_test: 1234
  dict_test:
    key1: hi
    key2: 5678
  about_to_remove: true
schema:
  value_test: int
  dict_test:
    key1: str
    key2: int
  about_to_remove: bool

 

[Dockerfile]

ARG BUILD_FROM
FROM $BUILD_FROM

COPY run.sh /
RUN chmod a+x /run.sh

CMD ["/run.sh"]

 

애드온을 빌드하고 HA에 설치한 뒤 '구성' 탭을 보면 위의 옵션들을 눈으로 확인할 수 있다


value_test 값을 1234에서 12345로 바꿔보자

[run.sh]

#!/usr/bin/with-contenv bashio

if bashio::config.exists 'value_test'; then
    echo "<value_test> option exist"
    $(bashio::addon.option 'value_test' 12345)
fi

애드온 로그

 

다시 애드온의 '구성' 탭으로 가면 value_test 값이 12345로 바뀐 것을 알 수 있다


딕셔너리 형태의 옵션을 바꿀 때는 다음과 같이 마침표로 키 값을 붙여주면 된다

dict_test 딕셔너리의 key1, key2의 값을 각각 hello, 8765로 바꿔보자

#!/usr/bin/with-contenv bashio

if bashio::config.exists 'dict_test.key1'; then
    echo "<dict_test.key1> option exist, will be changed"
    $(bashio::addon.option 'dict_test.key1' hello)
fi

if bashio::config.exists 'dict_test.key2'; then
    echo "<dict_test.key2> option exist, will be changed"
    $(bashio::addon.option 'dict_test.key2' 8765)
fi

애드온 로그

 

값이 바뀌긴 했는데 key2의 값이 정수형이 아니라 따옴표(")가 앞뒤로 붙은 문자열로 대입된다

이러면 schema가 깨져서 애드온이 정상 동작하지 않게 된다 

원인: bashio는 값에 해당하는 인자를 파싱할 때, 맨 앞글자에 ^ 문자가 있으면 뒤의 문자열을 따옴표를 붙이지 않고 값을 대입한다 (소스코드를 보면 바로 이해된다)

if bashio::var.has_value "${value}"; then
  item="\"$value\""
    if [[ "${value:0:1}" == "^" ]]; then
      item="${value:1}"
    fi

 

따옴표를 붙이지 않은 값으로 변경하고자 한다면 아래와 같이 바꾸면 된다

$(bashio::addon.option 'dict_test.key2' ^8765)

 

다시 빌드 후 실행해보면

 

원하는대로 정수값으로 교체된다

문자열(str) 데이터 타입이 아닌 경우 바꾸고자 하는 값 앞에 무조건 ^을 붙여주자
※ 문자열 데이터 타입도 붙여주는 게 좋다 (특별한 경우가 아니라면 따옴표를 쓸데없이 붙이지 말자)

마지막으로 옵션을 삭제하는 방법을 알아보자

※ 이미 애드온을 배포한 상태에서, 버전 업데이트 시 클라이언트의 로컬 컨테이너에 적용되어 있는 필요없는 옵션을 제거하고자 하는 경우에 필요한 기능

#!/usr/bin/with-contenv bashio

if bashio::config.exists 'about_to_remove'; then
    echo "<about_to_remove> option exist, will be removed"
    $(bashio::addon.option 'about_to_remove')
fi

 

앞서 설명했듯이, [<value>]란에 아무 값도 입력하지 않고 호출하면 해당 값이 옵션에서 삭제된다

 

이 때 새로 배포하는 애드온의 config.yaml에는 about_to_remove 항목을 전부 제거하고 배포해야 한다

[config.yaml]

options:
  value_test: 1234
  dict_test:
    key1: hi
    key2: 5678
  # about_to_remove: true
schema:
  value_test: int
  dict_test:
    key1: str
    key2: int
  # about_to_remove: bool

[참고]

bashio의 addon.option 함수 원형은 다음 깃허브 저장소에서 찾을 수 있다

https://github.com/hassio-addons/bashio/blob/main/lib/addons.sh

function bashio::addon.option() {
    local key=${1}
    local value=${2:-}
    local slug=${3:-'self'}
    local options
    local payload
    local item

    bashio::log.trace "${FUNCNAME[0]}" "$@"
    options=$(bashio::addon.options "${slug}")

    if bashio::var.has_value "${value}"; then
      item="\"$value\""
      if [[ "${value:0:1}" == "^" ]]; then
        item="${value:1}"
      fi

      if bashio::jq.exists "${options}" ".${key}"; then
        options=$(bashio::jq "${options}" ".${key} |= ${item}")
      else
        options=$(bashio::jq "${options}" ".${key} = ${item}")
      fi
    else
      options=$(bashio::jq "${options}" "del(.${key})")
    fi
    
    payload=$(bashio::var.json options "^${options}")
    bashio::api.supervisor POST "/addons/${slug}/options" "${payload}"

    bashio::cache.flush_all
}

 

코드를 보면 결국 HA Supervisor API를 호출하는 것을 알 수 있다

https://developers.home-assistant.io/docs/api/supervisor/endpoints#addons

 

Endpoints | Home Assistant Developer Docs

For API endpoints marked with you need use an authorization header with a Bearer token.

developers.home-assistant.io

 

API 호출을 위해서는 (1) slug명을 URL에 넣어야 하고 (2)SUPERVISOR_TOKEN 값을 얻어와야 하며 (3) POST 리퀘스트를 위한 헤더 생성 및 페이로드 생성을 포맷에 맞게 해줘야 하는데, bashio를 통해 코드 한 줄로 해결 가능하므로 Supervisor API를 본격적으로 개발할 게 아니라면 그냥 속편하게 bashio를 사용하자

반응형