barbitoff programmer`s blog

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

среда, 23 марта 2022 г.

Проверка сетевой доступности MongoDB Atlas кластера

Берем хостнэйм, указанный в connection string. Делаем:

dig -t SRV _mongodb._tcp.<хостнэйм из connection string>

либо

nslookup -q=SRV  _mongodb._tcp.<хостнэйм из connection string>

В ответ получаем записи вида:

_mongodb._tcp.***.mongodb.net        service = 0 0 1025 ***.mongodb.net.

_mongodb._tcp.***.mongodb.net        service = 0 0 1026 ***.mongodb.net.

_mongodb._tcp.***.mongodb.net        service = 0 0 1024 ***.mongodb.net. 

В правой части указаны хосты и порты фактических серверов. Теперь можно проверять сетевую доступность, например, с помощью nc:

nc -zv -w 5 ***.mongodb.net 1024 

Ограничение объема памяти, используемого WSL2

 Создаем файл %UserProfile%\.wslconfig, и в нем прописываем:

[wsl2]
memory=8GB

среда, 2 февраля 2022 г.

Установка podman на Ubuntu 18.04 / 20.04 под WSL2

Выполняем:

. /etc/os-release
sudo sh -c "echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/x${NAME}_${VERSION_ID}/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list"
wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/x${NAME}_${VERSION_ID}/Release.key -O Release.key
sudo apt-key add - < Release.key
sudo apt-get update -qq
sudo apt-get -qq -y install podman
sudo mkdir -p /etc/containers
echo -e "[registries.search]\nregistries = ['docker.io', 'quay.io']" | sudo tee /etc/containers/registries.conf 

Для Ubuntu 18.04 открываем конфигурационный файл

sudo nano /usr/share/containers/containers.conf

, и правим там следующие строки:

cgroup_manager = "cgroupfs"
...
events_logger = "file"

Если при запуске podman возникает ошибка:

cannot clone: Invalid argument
Error: cannot re-exec process

, вероятно, версия используемая версия WSL не 2, а 1. Это можно проверить командой: 

wsl --list -v

В колонке "VERSION" должна быть двойка, иначе нужно сделать апгрейд до версии 2 командой:

 wsl --set-version Ubuntu-20.04 2 

вторник, 25 января 2022 г.

Spring Boot: запуск кода до старта application

Задача

Запустить некий код до того, как начнет запускаться приложение. В моем случае нужно вызвать Security.addProvider().

Решение

Можно, конечно, сделать вызов в методе main() класса, аннотированного как @SpringBootApplication, перед тем, как вызывать SpringApplication.run():

@SpringBootApplication
public class AclImportApplication {
    public static void main(String[] args) {
        Security.addProvider(...);
        SpringApplication.run(AclImportApplication.class);
    }
}

Вот только код main() не вызывается при запуске @SpringBootTest, что создает необходимость создавать какие-то костыли для работоспособности тестов. Более правильный вариант - написать свою имплементацию интерфейса org.springframework.boot.SpringApplicationRunListener, где в методе starting() поместить нужный код. Имплементация должна обязательно иметь конструктор, принимающий SpringApplication app и String[] args, а также ссылку на имплементацию необходимо прописать в META-INF/spring.factories:

org.springframework.boot.SpringApplicationRunListener=my.custom.AppRunListener


четверг, 16 декабря 2021 г.

Подписывание docker-образов без docker cli

Задача

Нужно подписывать docker-образы подписями, совместимыми с docker trust, однако без использования docker-демона (т.к. подписание происходит в CI/CD без доступа к демону).

Решение

Для формирвания подписи необходимо 2 инструмента: 

  • notary cli для формирования подписи и ее загрузки на notary-сервер
  • skopeo для получения данных из манифеста подписываемого образа (умеет в т.ч. работать с докер-registry, а не только с локальным хранилищем образом, позволяя получать манифесты без pull'а самих образов)
# Если есть готовый docker-конфиг с учетками для авторизации в нужном docker registry,
# то указываем его для skopeo
export REGISTRY_AUTH_FILE=$HOME/.docker/config.json
# Вычислям хэш и размер манифеста докер-образа
MANIFEST_HASH=`skopeo inspect --raw docker://$IMAGE_NAME:$IMAGE_VERSION | sha256sum`
MANIFEST_HASH=${MANIFEST_HASH:0:64}
MANIFEST_SIZE=`skopeo inspect --raw docker://$IMAGE_NAME:$IMAGE_VERSION | wc -c`
# импортируем ключ для подписания из файла delegation.key (используемый рандомный passphrase)
export NOTARY_DELEGATION_PASSPHRASE=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c10)
notary key import ~/delegation.key -d ~/.docker/trust
# собственно подписание и загрузка подписи на Notary-сервер (с debug-выводом)
notary -D addhash -p $IMAGE_NAME $IMAGE_VERSION "$MANIFEST_SIZE" --sha256 "$MANIFEST_HASH" -r targets/releases -s https://my.notary.server -d ~/.docker/trust
Важный моментом является использование роли targets/releases при формировании подписи. Docker trust доверяет только этой роли, а также роли targets. Если использовать другую роль, докер будет считать, что образ не подписан (см. https://github.com/notaryproject/notary/blob/master/docs/advanced_usage.md#use-delegations-with-content-trust).