barbitoff programmer`s blog

Здесь я публикую заметки из программерской жизни: грабли, на которые мне случилось наступить, проблемы, для которых было найдено элегантное (или не очень) решение, а также все, с чем мне пришлось столкнуться и чем хотелось бы поделиться =)
PS Если хотите меня поблагодарить - на странице есть 3 места, чтобы это сделать =)

пятница, 9 января 2026 г.

Настройка mitmweb для учета HTTPS_PROXY и NO_PROXY

Задача

Нужно настроить mitmweb так, чтобы он перенаправлял исходящие запросы на другой прокси (корпоративный), учитывая HTTPS_PROXY и NO_PROXY переменные окружения.

Решение

Создаем py-скрипт для обработки NO_PROXY, называем его exclude_proxy.py:

import os

from mitmproxy import http


# Read the exclusions from the NO_PROXY environment variable

# Split the environment variable by commas to handle multiple hostnames

NO_PROXY = os.getenv("NO_PROXY", "").split(",")


def request(flow: http.HTTPFlow):

    # Check if the hostname matches any entry in NO_PROXY

    for hostname in NO_PROXY:

        # Ensure no leading/trailing whitespace in the hostname

        hostname = hostname.strip()

        # If the flow's request host matches an entry in NO_PROXY, bypass the proxy

        if hostname and hostname in flow.request.host:

            flow.server_conn.via = None

Запускаем mitmweb:

mitmweb --mode upstream:$HTTPS_PROXY -s exclude_proxy.py 

вторник, 16 сентября 2025 г.

Claude отвечает пустым ответом

Согласно документации https://docs.anthropic.com/en/api/messages, при передаче Клоду нескольких сообщений в случае, когда последнее сообщение имеет role=assistant, модель будет дополнять это сообщение. Однако в случае, если это последнее сообщение с точки зрения модели выглядит законченным (не обрывается на полуслове или на середине мысли), модель может вернуть пустой ответ.

вторник, 10 июня 2025 г.

Google ADK + AWS Bedrock + Claude

Google ADK "из коробки" не поддерживает работу с AWS Bedrock. Можно его подключить через LiteLLM, но это может быть сопряжено с трудностями, например, из-за конфликта версий зависимостей. Есть вариант проще - подключить зависимость anthropic[bedrock], после чего отнаследоваться от класса модели Claude, входящего в ADK и использующего VertexAI, заменив клиента на Bedrock-клиента. Dirty, но работает:

import os
import httpx
from functools import cached_property
from typing_extensions import override
from google.adk.models.anthropic_llm import Claude
from google.adk.models.registry import LLMRegistry
from anthropic import AnthropicBedrock class ClaudeOnBedrock(Claude):
    @staticmethod
    @override
    def supported_models() -> list[str]:
        return [r".*anthropic.claude-3-.*", r".*anthropic.claude-.*-4.*"]
   
    @override
    @cached_property
    def _anthropic_client(self) -> AnthropicBedrock:
        proxy = os.getenv("HTTPS_PROXY")
        if proxy:
            return AnthropicBedrock(http_client=httpx.Client(proxy=proxy),
                aws_region="***")
        return AnthropicBedrock(aws_region="***")

# Register the custom model
LLMRegistry.register(ClaudeOnBedrock)

Google ADK + VertexAI + Claude: работа за HTTP прокси

Проблема

Пытаюсь запустить решение на Google ADK, использующее VertexAI и одну из моделей Claude, за HTTP прокси-сервером. Вызов идет мимо прокси, что приводит к ошибке, хотя прокси прописан в переменной окружения HTTPS_PROXY.

Решение

Вручную расширить класс ADK-модели Claude, добавив поддержку прокси:

from google.adk.agents import Agent
from google.adk.models.anthropic_llm import Claude
from google.adk.models.registry import LLMRegistry
from anthropic import AnthropicVertex
from functools import cached_property
import os
import httpx

class ClaudeWithProxySupport(Claude):
    @cached_property
    def _anthropic_client(self) -> AnthropicVertex:
        proxy = os.getenv("HTTPS_PROXY")
        if not proxy:
            return super()._anthropic_client

        if (
            "GOOGLE_CLOUD_PROJECT" not in os.environ
            or "GOOGLE_CLOUD_LOCATION" not in os.environ
        ):
            raise ValueError(
                "GOOGLE_CLOUD_PROJECT and GOOGLE_CLOUD_LOCATION must be set "
                "for using Anthropic on Vertex."
            )

        return AnthropicVertex(
            project_id=os.environ["GOOGLE_CLOUD_PROJECT"],
            region=os.environ["GOOGLE_CLOUD_LOCATION"],
            http_client=httpx.Client(proxy=proxy),
        )


# Register the custom model
LLMRegistry.register(ClaudeWithProxySupport) 

пятница, 30 мая 2025 г.

WSL и VPN

Проблема

Есть Windows хост с поднятым корпоративным VPN. Есть гостевой Linux в WSL (конкретно, WSL2). На Windows весь трафик идет через VPN, трафик в обход VPN заблокирован, доступ в интернет только через корпоративный прокси.

В Linux недоступна ни корпоративная сеть, ни интернет (т.к. недоступен корпоративный прокси, расположенный в корпоративной сети), т.к. трафик не заворачивается в VPN.

Решение

https://github.com/sakai135/wsl-vpnkit?tab=readme-ov-file - скачиваем, устанавливаем, запускаем по инструкции. Трафик из WSL начинает заворачиваться в VPN, в результате чего в Linux появляется доступ к корпоративной сети и интернету (через корпоративную проксю).

четверг, 24 апреля 2025 г.

Logitech Options+ за прокси

Обычная версия Logitech Options+ отказывается корректно работать за корпоративным прокси: установка проходит успешно, однако проверка обновлений, а также загрузка информации о девайсах не работает, в итоге ни один девайс добавить не получаестя. Решение - использовать оффлайн-установщик, он не требует подключения к интернету для загрузки информации о девайсах: https://prosupport.logi.com/hc/en-us/articles/10991109278871-Logitech-Options-Offline-Installer

вторник, 29 октября 2024 г.

gitleaks ломает мердж в Idea

Проблема

Пытаюсь смерджить две ветки в IntelliJ Idea, после разрешения конфликтов появляется уведомление:


В итоге мердж можно только откатить. Причина ясна - gitleaks нашел какую-то уязвимость в коде, который мерджится. Но что если это false-positive и мы хотим все же смерджиться?

Решение

Идем в .git/hooks/pre-commit, там комментим вызов gitleaks:

#"C:\Program Files\Git\gitleaks.exe" protect -v --staged

После мерджа строчку можно раскомментить обратно. 



пятница, 20 сентября 2024 г.

Linux Mint: ноутбук засыпает при отключении внешнего монитора при закрытой крышке

Проблема

Ноутбук с Linux Mint работает с закрытой крышкой и внешним монитором. Стоит отключить внешний монитор (точнее, я просто переключаю монитор на другой ноутбук через KVM Switch), ноутбук уходит в сон, хотя в настройках питания стоит "ничего не делать" по закрытию крышки (собственно, по закрытию крышки он и не засыпает).

Решение

В файле /etc/systemd/logind.conf строчки:

#HandleLidSwitch=suspend
#HandleLidSwitchExternalPower=suspend

заменяем на 

HandleLidSwitch=ignore
HandleLidSwitchExternalPower=ignore

И делаем:

sudo service systemd-logind restart

четверг, 19 сентября 2024 г.

Spring Boot with Gradle in IntelliJ Idea: profiler cannot connect to the application

When I'm trying to profile my Spring Boot application, built with Gradle and run with :bootRun, in IntelliJ Idea, I face the following error:

"Cannot connect to target JVM. Exception creating connection to: 192.168.x.x; ..."

The reason is obviously in the fact, that IntelliJ tries to use my IP from the network card instead of localhost. 

To change that, in my build.gradle I configured the bootRun task in the following way:

bootRun {

    jvmArgs('-Djava.rmi.server.hostname=localhost')

}


вторник, 18 июня 2024 г.

Linux Mint и TP-link Archer T4U v3

Годы идут, а установка драйверов для некоторого железа в Linux все также периодически требует нетривиальных действий. Актуальный на июнь 2024 года Linux Mint "из коробки" не видит внешний WiFi-адаптер TP-link Archer T4U v3. Официальных драйверов под актуальные ядра Linux производитель не предоставляет, приходится делать следующее:

sudo apt install git dkms
git clone https://github.com/cilynx/rtl88x2bu.git
sudo dkms add ./rtl88x2bu
sudo dkms install rtl88x2bu/5.8.7.1 

После - перезагрузка. 

понедельник, 8 апреля 2024 г.

Установка дополнений в OpenLens вручную

Иногда невозможно воспользоваться автоматической установкой дополнений в OpenLens, например, если из OpenLens нет доступа в интернет. Тогда можно сделать следующее (в примере я устанавливаю дополнение @alebcay/openlens-node-pod-menu):

npm pack @alebcay/openlens-node-pod-menu

В папке появится tgz-архив, и вот его уже можно установить через выбор файла вручную в меню Extensions в OpenLens.

понедельник, 10 июля 2023 г.

initialDelaySeconds в Kubernetes Probes

В Kubernetes для probes (например, readinessProbe) есть параметр initialDelaySeconds, предназначенный для того, чтобы дать контейнеру некоторое время на инициализацию, прежде чем Kubernetes начнет выполнять ту или иную probe.

Можно подумать, что этот параметр буквально задает "отсрочку" для начала выполнения той или иной probe. Т.е., к примеру, в такой конфигурации:

          readinessProbe:
            httpGet:
              path: /actuator/health/readiness
              port: http
              scheme: HTTP
            initialDelaySeconds: 20
            timeoutSeconds: 5
            periodSeconds: 15
            successThreshold: 1
            failureThreshold: 5

можно ожидать, что первый раз probe будет выполнен через 20 сек после запуска контейнера, потому что в initialDelaySeconds указано 20. 

Однако, это не так. Отсчет периодов для выполнения probe начинается в момент запуска контейнера вне зависимости от того, установлен ли initialDelaySeconds или нет. Т.е. probe будет запланирован на запуск в 0сек, 15сек, 30сек, 45сек и т.д. начиная от момента запуска контейнера. То, что initialDelaySeconds равен 20, приведет лишь к тому, что те попытки выполнить probe, которые попадут в эти первые 20сек, будут пропущены:

Таким образом, первый раз readiness probe сработает не через 20 сек после запуска контейнера, а через 30 сек. 

пятница, 5 мая 2023 г.

Ubuntu 20.04 + Podman: error "potentially insufficient UIDs or GIDs available in user namespace" when trying to run a container

Проблема

При попытке запустить контейнер с помощью Podman появляется ошибка:

Error: writing blob: adding layer with blob "sha256:...": Error processing tar file(exit status 1): potentially insufficient UIDs or GIDs available in user namespace (requested 110779:100 for /usr/local/lib/node_modules/@stoplight/spectral/node_modules/optionator/CHANGELOG.md): Check /etc/subuid and /etc/subgid: lchown /usr/local/lib/node_modules/@stoplight/spectral/node_modules/optionator/CHANGELOG.md: invalid argument

Причина

На эту тему есть отличная статья https://www.redhat.com/sysadmin/rootless-podman, в двух словах - причина в том, что UID 110779, используемый в docker-образе, не может быть смапплен в хост-ОС из-за того, что он больше, чем 65536.

Решение

Правим на хост-ОС файл /etc/subuid, заменяя для пользователя, из-под которого запускается podman, ограничение 65536 на другое, большее чем UID, фигурирующий в ошибке, например:

aspirinspb:100000:165536

Podman: WARN[0000] "/" is not a shared mount, this could cause issues or missing mounts with rootless containers

Проблема

При старте Podman появляется warning:

WARN[0000] "/" is not a shared mount, this could cause issues or missing mounts with rootless containers

Решение

sudo mount --make-rshared /

(необходимо выполнять после каждого перезапуска ОС либо добавить в какой-то из startup-скриптов) 

WSL2 + Cisco VPN: чиним доступность сети в гостевой ОС

Проблема

Хост-машина с Windows 10 + Cisco AnyConnect VPN, заворачивающим весь траффик в туннель. Под WSL1 в гостевой ОС (Ubuntu 20.04) все ок, но после миграции на WSL2 пропадает есть.

Решение

В моем случае причина была в том, что трафик заворачивался в неверный сетевой интерфейс (не в VPN), и решилась установкой для VPN-интерфейса более высокого значения метрики командой в PowerShell из-под администратора:

Get-NetAdapter | Where-Object {$_.InterfaceDescription -Match "Cisco AnyConnect"} | Set-NetIPInterface -InterfaceMetric 6000

(имя интерфейса "Cisco AnyConnect" возможно придется заменить на актуальное имя сетевого интерфейса VPN-соединения). Команду нужно выполнять после каждой перезагрузки хост-машины либо реконнекта VPN.

вторник, 4 апреля 2023 г.

Spring Boot 3: micrometer-tracing не работает в @SpringBootTest

Проблема

Есть приложение на Spring Boot 3, использующее для трейсинга micrometer-tracing-bridge-brave и zipkin-reporter-brave. Есть @SpringBootTest, который, в числе прочего, проверяет пропагирование трейс-информации (а именно, заголовка "b3") из входящих http-запросов в исходящие http-запросы. Однако тест падает - в исходящие запросы заголовок "b3" не добавляется. Хотя если запустить приложение и выполнить "ручную" проверку - заголовок "b3" в исходящих запросах есть.

Решение

Observability-функциональность по-умолчанию отключена для @SpringBootTest. Включается аннотацией @AutoConfigureObservability на тест-классе.

понедельник, 27 марта 2023 г.

Grafana Loki: фильтрация по полю из JSON

 Если в Grafana Loki необходимо выполнить поиск по одному из полей JSON-лога, то делается это следдующим образом:

Сначала достаем поле из JSON и делаем из него лэйбл, затем добавляем фильтрацию по этому лэйблу.

вторник, 28 июня 2022 г.

Excel: преобразование времени в миллисекунды

Задача

Есть ячейка со строкой - временем в формате ЧЧ:ММ:СС.млс (например, 18:45:13.785). Необходимо преобразовать это значение в число миллисекунд.

Решение

Если представить, что исходная строка находится в ячейке A1, формула будет выглядеть следующим образом:

=LEFT(A1; 2)*3600000 + MID(A1; 4; 2) * 60000 + MID(A1; 7; 2)*1000 + RIGHT(A1; 3)

пятница, 13 мая 2022 г.

Gradle: установка переменных окружения

 Читать переменные окружения gradle умеет:

 System.getenv("HOME")

А вот устанавливать - нет, метод а-ля System.setenv() отсутствует. Однако, в задачах, запускающих отдельный процесс, можно установить переменную окружения для этого отдельно стартующего процесса, например:

task('myTask', type:Exec) {
    environment "FOO", "bar"
    workingDir '.'
    commandLine 'cmd', '/c', 'print.bat'
}

вторник, 5 апреля 2022 г.

WSL2: высвобождение места, занимаемого диском гостевой ОС

Проблема

Есть WSL2 и Ubuntu под ним. После некоторых действий в Ubuntu создалось большое количество больших и ненужных файлов, заметил я это по росту файла C:\Users\%USER%\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu18.04onWindows_79rhkp1fndgsc\LocalState\ext4.vhdx. Сами ненужные файлы в Ubuntu я почистил, однако, vhdx-файл не уменьшился. Команда df в Ubuntu показывает утилизацию места на основном томе всего в 3%.

Решение

В powershell-консоли, запущенной с правами администратора, переходим в директорию, где лежит  vhdx-файл, выполняем:

wsl --shutdown
optimize-vhd -Path .\ext4.vhdx -Mode full