###################################################################### # @CCOSTAN - Follow Me on X # For more info visit https://www.vcloudinfo.com/click-here # Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig # ------------------------------------------------------------------- # Docker Infrastructure - Host patching and container alerts # APT webhook results (docker_10/14/17/69) and container down repairs. # ------------------------------------------------------------------- # Notes: Hosts run weekly Wed 12:00 APT job and POST JSON to webhooks. # Notes: Reboots are handled directly on each host by apt_weekly.sh. # Notes: Reboot staggering: docker_14 first, docker_69 second, docker_10 third. # Notes: Container watchlist is explicit; extend entity list as needed. ###################################################################### input_datetime: apt_docker_10_last_check: name: "docker_10 APT last check" has_date: true has_time: true apt_docker_10_last_update: name: "docker_10 APT last update" has_date: true has_time: true apt_docker_17_last_check: name: "docker_17 APT last check" has_date: true has_time: true apt_docker_17_last_update: name: "docker_17 APT last update" has_date: true has_time: true apt_docker_14_last_check: name: "docker_14 APT last check" has_date: true has_time: true apt_docker_14_last_update: name: "docker_14 APT last update" has_date: true has_time: true apt_docker_69_last_check: name: "docker_69 APT last check" has_date: true has_time: true apt_docker_69_last_update: name: "docker_69 APT last update" has_date: true has_time: true input_text: apt_docker_10_last_result: name: "docker_10 APT last result" max: 255 apt_docker_17_last_result: name: "docker_17 APT last result" max: 255 apt_docker_14_last_result: name: "docker_14 APT last result" max: 255 apt_docker_69_last_result: name: "docker_69 APT last result" max: 255 template: - sensor: - name: "docker_10 APT status" unique_id: apt_docker_10_status icon: mdi:package-up state: "{{ states('input_text.apt_docker_10_last_result') }}" - name: "docker_10 APT last check" unique_id: apt_docker_10_last_check device_class: timestamp state: >- {% set stamp = states('input_datetime.apt_docker_10_last_check') %} {% if stamp not in ['unknown', 'unavailable', 'none', ''] %} {{ as_local(as_datetime(stamp)) }} {% endif %} - name: "docker_10 APT last update" unique_id: apt_docker_10_last_update device_class: timestamp state: >- {% set stamp = states('input_datetime.apt_docker_10_last_update') %} {% if stamp not in ['unknown', 'unavailable', 'none', ''] %} {{ as_local(as_datetime(stamp)) }} {% endif %} - name: "docker_14 APT status" unique_id: apt_docker_14_status icon: mdi:package-up state: "{{ states('input_text.apt_docker_14_last_result') }}" - name: "docker_17 APT status" unique_id: apt_docker_17_status icon: mdi:package-up state: "{{ states('input_text.apt_docker_17_last_result') }}" - name: "docker_17 APT last check" unique_id: apt_docker_17_last_check device_class: timestamp state: >- {% set stamp = states('input_datetime.apt_docker_17_last_check') %} {% if stamp not in ['unknown', 'unavailable', 'none', ''] %} {{ as_local(as_datetime(stamp)) }} {% endif %} - name: "docker_17 APT last update" unique_id: apt_docker_17_last_update device_class: timestamp state: >- {% set stamp = states('input_datetime.apt_docker_17_last_update') %} {% if stamp not in ['unknown', 'unavailable', 'none', ''] %} {{ as_local(as_datetime(stamp)) }} {% endif %} - name: "docker_14 APT last check" unique_id: apt_docker_14_last_check device_class: timestamp state: >- {% set stamp = states('input_datetime.apt_docker_14_last_check') %} {% if stamp not in ['unknown', 'unavailable', 'none', ''] %} {{ as_local(as_datetime(stamp)) }} {% endif %} - name: "docker_14 APT last update" unique_id: apt_docker_14_last_update device_class: timestamp state: >- {% set stamp = states('input_datetime.apt_docker_14_last_update') %} {% if stamp not in ['unknown', 'unavailable', 'none', ''] %} {{ as_local(as_datetime(stamp)) }} {% endif %} - name: "docker_69 APT status" unique_id: apt_docker_69_status icon: mdi:package-up state: "{{ states('input_text.apt_docker_69_last_result') }}" - name: "docker_69 APT last check" unique_id: apt_docker_69_last_check device_class: timestamp state: >- {% set stamp = states('input_datetime.apt_docker_69_last_check') %} {% if stamp not in ['unknown', 'unavailable', 'none', ''] %} {{ as_local(as_datetime(stamp)) }} {% endif %} - name: "docker_69 APT last update" unique_id: apt_docker_69_last_update device_class: timestamp state: >- {% set stamp = states('input_datetime.apt_docker_69_last_update') %} {% if stamp not in ['unknown', 'unavailable', 'none', ''] %} {{ as_local(as_datetime(stamp)) }} {% endif %} automation: - alias: "APT Update Report - Docker Hosts" id: apt_update_report_docker_hosts description: "Receive docker host APT results and update helpers/logbook." mode: queued trigger: - platform: webhook webhook_id: !secret apt_webhook_docker_10 id: docker_10 allowed_methods: - POST local_only: true - platform: webhook webhook_id: !secret apt_webhook_docker_14 id: docker_14 allowed_methods: - POST local_only: true - platform: webhook webhook_id: !secret apt_webhook_docker_17 id: docker_17 allowed_methods: - POST local_only: true - platform: webhook webhook_id: !secret apt_webhook_docker_69 id: docker_69 allowed_methods: - POST local_only: true variables: host_id: "{{ trigger.id }}" payload: "{{ trigger.json | default({}) }}" success: "{{ payload.get('success', true) | bool }}" updated: "{{ payload.get('updated', false) | bool }}" reboot_required: "{{ payload.get('reboot_required', false) | bool }}" packages: "{{ payload.get('packages', 0) | int(0) }}" message: "{{ payload.get('message', '') | string }}" helpers: docker_10: last_check: input_datetime.apt_docker_10_last_check last_update: input_datetime.apt_docker_10_last_update last_result: input_text.apt_docker_10_last_result docker_14: last_check: input_datetime.apt_docker_14_last_check last_update: input_datetime.apt_docker_14_last_update last_result: input_text.apt_docker_14_last_result docker_17: last_check: input_datetime.apt_docker_17_last_check last_update: input_datetime.apt_docker_17_last_update last_result: input_text.apt_docker_17_last_result docker_69: last_check: input_datetime.apt_docker_69_last_check last_update: input_datetime.apt_docker_69_last_update last_result: input_text.apt_docker_69_last_result host_helpers: "{{ helpers[host_id] if host_id in helpers else none }}" result: >- {% if not success %} ERROR{% if (message | trim) != '' %}: {{ message | trim }}{% endif %} {% elif updated %} UPDATED {{ packages }} PKGS{% if reboot_required %} (REBOOT REQ){% endif %} {% elif reboot_required %} NO UPDATES (REBOOT REQ) {% else %} NO UPDATES {% endif %} log_message: >- {{ host_id }} updated {{ packages }} package{% if packages != 1 %}s{% endif %}{% if reboot_required %}; reboot required{% endif %}. condition: - condition: template value_template: "{{ host_helpers is not none }}" action: - service: input_datetime.set_datetime target: entity_id: "{{ host_helpers.last_check }}" data: datetime: "{{ now().strftime('%Y-%m-%d %H:%M:%S') }}" - service: input_text.set_value target: entity_id: "{{ host_helpers.last_result }}" data: value: "{{ result }}" - choose: - conditions: "{{ success and updated }}" sequence: - service: input_datetime.set_datetime target: entity_id: "{{ host_helpers.last_update }}" data: datetime: "{{ now().strftime('%Y-%m-%d %H:%M:%S') }}" - service: script.send_to_logbook data: topic: "APT" message: "{{ log_message }}" - alias: "Docker Container Offline - Create Repairs" id: docker_container_offline_repairs_create description: "Create a Repairs issue when a watched container is down for 5+ minutes." mode: parallel trigger: - platform: state entity_id: - sensor.rc_price_checker_state - switch.rc_price_checker_container to: "unavailable" for: "00:05:00" - platform: state entity_id: - sensor.rc_price_checker_state to: "unknown" for: "00:05:00" - platform: state entity_id: - sensor.rc_price_checker_state to: "restarting" for: "00:05:00" - platform: state entity_id: - switch.rc_price_checker_container to: "off" for: "00:05:00" variables: issue_id: "docker_container_{{ trigger.entity_id | replace('.', '_') }}" container_name: >- {{ state_attr(trigger.entity_id, 'friendly_name') | default(trigger.entity_id) }} current_state: "{{ states(trigger.entity_id) }}" action: - service: repairs.create data: issue_id: "{{ issue_id }}" title: "Container offline: {{ container_name }}" description: >- {{ container_name }} has been {{ current_state }} for over 5 minutes. Entity: {{ trigger.entity_id }}. severity: warning persistent: true - alias: "Docker Container Offline - Clear Repairs" id: docker_container_offline_repairs_clear description: "Clear Repairs issue once the watched container is back online." mode: parallel trigger: - platform: state entity_id: - sensor.rc_price_checker_state - switch.rc_price_checker_container variables: issue_id: "docker_container_{{ trigger.entity_id | replace('.', '_') }}" condition: - condition: template value_template: >- {{ states(trigger.entity_id) not in ['unavailable', 'unknown', 'restarting', 'off'] }} action: - service: repairs.remove continue_on_error: true data: issue_id: "{{ issue_id }}"