barbitoff programmer`s blog

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

пятница, 21 февраля 2020 г.

echo и многострочные переменные окружения

Задача

Есть переменная окружения, содержащая текст с несколькими строками. Нужно сделать echo этой переменной так, чтобы не потерялись переводы строк.

Решение

Если делать просто echo $var, переносы строки теряются. А вот если заключить переменную в кавычки:
echo "$var"
,то строки выводятся корректно.

среда, 19 февраля 2020 г.

GitLab CI/CD и Gradle: корректное кэширование и передача результатов запуска между джобами

Кейс

Есть проект, собираемый при помощи Gradle, и CI/CD-пайплайн в GitLab, выполняющий некоторые Gradle-таски на разных stage. Необходимо:

  1. Реализовать кэширование зависимостей, чтобы не выкачивать их заново на каждом stage, а также при каждом новом запуске pipeline
  2. Реализовать кэширование результатов сборки, чтобы последующий stage выполнял не всю сборку "с нуля", а использовал результаты предыдущих stage'й
Решение

Во-первых, настраиваем GRADLE_USER_HOME, чтобы он размещался внутри сборочной директории, и настраиваем кэширование для папки с зависимостями внутри GRADLE_USER_HOME в соответствии с https://docs.gradle.org/6.1.1/userguide/dependency_resolution.html#sec:dependency_cache:
before_script:
  - export GRADLE_USER_HOME=`pwd`/.gradle
myjob:
  ...
  cache:
    key: gradle_modules_cache
    paths:
      - .gradle/caches/modules-2
    policy: pull-push
Т.к. это кэш, он будет разделяться не только джобами внутри пайплайна, но и между разными пайплайнами.

Во-вторых, в settings.gradle настраиваем кастомную директорию для билд-кэша (см. https://docs.gradle.org/current/userguide/build_cache.html):
buildCache {
    local {
        directory = new File(rootDir, 'build-cache')
    }
}
и для промежуточных джобов настраиваем публикацию этой директории в качестве артефакта:
  artifacts:
    paths:
      - build-cache/
    expire_in: 1 hour
В последующих джобах прописываем dependencies на предыдущие джобы, чтобы они подхватывали build-cache/ оттуда. Таким образом, build cache будет передаваться между джобами, но не будет передаваться между пайплайнами, что как раз корректно.

Ну и последнее - при вызове gradle используем --build-cache, чтобы собственно включить использования билд-кэша.

Вуаля, в логах сборки видим, что результаты предыдущих джобов подтягиваются из кэша:


вторник, 11 февраля 2020 г.

Windows 10 и несколько мониторов: отображение на таскбаре каждого монитора только находящихся на нем окон

Задача

Есть машина с Windows 10 и несколькими мониторами. Хочется, чтобы на каждом мониторе был таскбар, и на каждом таскбаре отображались иконки только тех окон, которые действительно находятся на этом мониторе.

Решение

Долгие годы для этих целей использовал замечательную программу DisplayFusion, честно купленную на Steam. Но только сегодня выяснил, что подобное поведение можно настроить в Windows "из коробки": идем в Settings -> Taskbat settings и там устанавливаем:

вторник, 4 февраля 2020 г.

Docker Desktop: рассинхронизация времени в контейнерах и у хоста

Проблема

Неожиданно обнаружилось, что все контейнеры, работающие в Docker Desktop, видят время, отстающее от времени хоста аж на 6 с лишним дней.

Решение

Корень проблемы не ясен, но рестарт Docker Desktop помог.

пятница, 31 января 2020 г.

bash: ожидание, пока не будет открыт порт

Задача

В bash-скрипте нужно подождать, пока не станет доступен определенный tcp-порт, но ждать нужно не более определенного времени.

Решение
for ((i=0;  i< 10; i++)) do if(nc -q0 localhost 8080 < /dev/null > /dev/null 2>&1) then break; fi; echo "sleeping"; sleep 2; done

Раз в 2 секунды проверяем открытость localhost:8080, но не более 10 проверок. Такой вариант работает в Ubuntu 18.04, а вот с CentOS пришлось убрать -q0 опцию, т.к. она там не поддерживается.

вторник, 28 января 2020 г.

Grafana в Kubernetes: автоматизация развертывания дашбордов

Задача 

Есть JSON/YAML-описания дашбордов для графаны, выкладываемые разработчиками в gitlab. Необходимо в CI/CD-пайплайне автоматизировать развертывание этих дашборд на окружении при условии, что графана установлена внутри Kubernetes.

Решение

На тему автоматизации развертывания дашбордов в случае, когда Grafana работает в Kubernetes, есть отличная статья: https://medium.com/@chris_linguine/how-to-monitor-your-kubernetes-cluster-with-prometheus-and-grafana-2d5704187fc8. В целом, сценарий выглядит следующим образом:
  1. Описания дашбордов пакуем внутрь ConfigMap-объектов Kubernetes и разворачиваем эти объекты в кластере (делаем kubectl apply -f ... внутри нашего CI/CD pipeline)
  2. Графану конфигурируем (путем установки необходимых значений в helm) таким образом, чтобы она разворачивалась с сайдкаром, который будет мониторить наличие ConfigMap-объектов с описаниям дашбордов и "скармливать" эти описания работающей графане.