diff --git a/.gitea/workflows/docker.yaml b/.gitea/workflows/docker.yaml index 80a486d..1a7b2ec 100644 --- a/.gitea/workflows/docker.yaml +++ b/.gitea/workflows/docker.yaml @@ -1,20 +1,27 @@ -name: ci +name: Publish telemt-api gateway Docker image on: push: - branches: [main, master] - tags: ["v*"] - pull_request: + branches: + - "**" + tags: + - "*" + workflow_dispatch: env: GO_VERSION: "1.22" + REGISTRY: git.shts.su + IMAGE_REPO: ${{ gitea.repository }} jobs: test: runs-on: ubuntu-latest + timeout-minutes: 10 steps: - - name: Checkout + - name: Checkout repository uses: actions/checkout@v4 + with: + fetch-depth: 1 - name: Set up Go uses: actions/setup-go@v5 @@ -24,38 +31,70 @@ jobs: - name: Test run: go mod tidy && go test ./... - docker: - needs: test + build-and-push: runs-on: ubuntu-latest + needs: test + timeout-minutes: 20 + permissions: + contents: read + packages: write + steps: - - name: Checkout + - name: Checkout repository uses: actions/checkout@v4 + with: + fetch-depth: 1 - - name: Build image - run: docker build -t telemt-api:ci . + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + driver-opts: | + image=moby/buildkit:v0.13.2 - - name: Push to registry - if: github.event_name == 'push' + - name: Log in to Gitea Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ gitea.actor }} + password: ${{ secrets.ACTIONS_PAT }} + + - name: Prepare Docker tags + id: prep + shell: bash env: - REGISTRY_IMAGE: ${{ secrets.REGISTRY_IMAGE }} - REGISTRY_URL: ${{ secrets.REGISTRY_URL }} - REGISTRY_USER: ${{ secrets.REGISTRY_USER }} - REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} + REPO: ${{ gitea.repository }} + SHA: ${{ gitea.sha }} + REF_NAME: ${{ gitea.ref_name }} run: | - set -e - if [ -z "$REGISTRY_IMAGE" ] || [ -z "$REGISTRY_URL" ] || [ -z "$REGISTRY_USER" ] || [ -z "$REGISTRY_PASSWORD" ]; then - echo "Registry secrets not set (REGISTRY_IMAGE, REGISTRY_URL, REGISTRY_USER, REGISTRY_PASSWORD) — push skipped." - exit 0 - fi - echo "$REGISTRY_PASSWORD" | docker login "$REGISTRY_URL" -u "$REGISTRY_USER" --password-stdin - docker tag telemt-api:ci "${REGISTRY_IMAGE}:sha-${GITHUB_SHA}" - docker push "${REGISTRY_IMAGE}:sha-${GITHUB_SHA}" - if [ "${GITHUB_REF}" = "refs/heads/main" ] || [ "${GITHUB_REF}" = "refs/heads/master" ]; then - docker tag telemt-api:ci "${REGISTRY_IMAGE}:latest" - docker push "${REGISTRY_IMAGE}:latest" - fi - if echo "${GITHUB_REF}" | grep -q '^refs/tags/'; then - TAG="${GITHUB_REF#refs/tags/}" - docker tag telemt-api:ci "${REGISTRY_IMAGE}:${TAG}" - docker push "${REGISTRY_IMAGE}:${TAG}" - fi + set -euo pipefail + IMAGE="${REGISTRY}/${REPO}" + BRANCH_OR_TAG="${REF_NAME:-unknown}" + SAFE_REF="$(echo "${BRANCH_OR_TAG}" | tr '/' '-')" + SHORT_SHA="$(echo "${SHA}" | cut -c1-12)" + + TAGS="$(printf '%s\n%s\n%s\n' \ + "${IMAGE}:latest" \ + "${IMAGE}:${SAFE_REF}" \ + "${IMAGE}:sha-${SHORT_SHA}")" + + echo "tags<> "${GITHUB_OUTPUT}" + echo "${TAGS}" >> "${GITHUB_OUTPUT}" + echo "EOF" >> "${GITHUB_OUTPUT}" + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + file: ./Dockerfile + push: true + platforms: linux/amd64 + cache-from: | + type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_REPO }}:latest + cache-to: type=inline + tags: ${{ steps.prep.outputs.tags }} + labels: | + org.opencontainers.image.title=telemt-api-gateway + org.opencontainers.image.description=HTTP gateway with IP whitelist and Telemt Control API proxy by alias + org.opencontainers.image.revision=${{ gitea.sha }} + org.opencontainers.image.source=${{ gitea.server_url }}/${{ gitea.repository }} + provenance: false diff --git a/README.md b/README.md new file mode 100644 index 0000000..008c0df --- /dev/null +++ b/README.md @@ -0,0 +1,45 @@ +# telemt-api + +HTTP‑шлюз на Go для [Telemt Control API](docs/API.md): один порт, **белый список IP (CIDR)**, маршруты вида `/api/{alias}/…` → `{base_url}/v1/…`, метрики Prometheus на `/metrics`. + +## Быстрый старт (Linux) + +Предполагается установлены Docker и Docker Compose v2. + +```bash +git clone && cd telemt-api +cp config.example.yaml config.yaml +# отредактируйте config.yaml: servers, whitelist_cidrs или allow_all для разработки +docker build -t telemt-api-gateway:local . +docker run -d --name telemt-gateway \ + -p 8080:8080 \ + -v "$(pwd)/config.yaml:/etc/telemt-gateway/config.yaml:ro" \ + -e CONFIG_PATH=/etc/telemt-gateway/config.yaml \ + telemt-api-gateway:local +curl -sS http://127.0.0.1:8080/health +curl -sS http://127.0.0.1:8080/api/main_srv/health +``` + +Или через Compose (пример конфига смотрите в `config.compose.yaml`): + +```bash +docker compose up -d --build +docker compose logs -f gateway +``` + +## Документация + +| Документ | Содержание | +|----------|------------| +| **[docs/GATEWAY_RUN.md](docs/GATEWAY_RUN.md)** | Полная инструкция: конфиг, Docker CLI, Compose, CI/CD, неполадки | +| **[docs/API.md](docs/API.md)** | Контракт Telemt Control API (`/v1/…`) | + +## Сборка и тесты без Docker + +```bash +go mod tidy && go test ./... +``` + +## CI/CD + +В репозитории: [.gitea/workflows/docker.yaml](.gitea/workflows/docker.yaml) — тесты Go, сборка и публикация образа в Container Registry Gitea (см. раздел «Обновление и CI/CD» в [docs/GATEWAY_RUN.md](docs/GATEWAY_RUN.md)). diff --git a/config.compose.yaml b/config.compose.yaml index 63c5c27..3b5f692 100644 --- a/config.compose.yaml +++ b/config.compose.yaml @@ -1,9 +1,9 @@ # Пример для docker compose: без whitelist (только для локальной проверки). +# На Linux в docker-compose.yml задано extra_hosts host.docker.internal:host-gateway. listen: ":8080" allow_all: true whitelist_cidrs: [] trusted_proxies: [] servers: - alias: main_srv - # Telemt на хосте Windows/macOS/Linux: base_url: http://host.docker.internal:9091 diff --git a/docker-compose.yml b/docker-compose.yml index cdf42cc..dd0673f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,3 +8,6 @@ services: - ./config.compose.yaml:/etc/telemt-gateway/config.yaml:ro environment: CONFIG_PATH: /etc/telemt-gateway/config.yaml + # Доступ к Telemt на хосте Linux (host.docker.internal в config.compose.yaml): + extra_hosts: + - "host.docker.internal:host-gateway" diff --git a/docs/GATEWAY_RUN.md b/docs/GATEWAY_RUN.md index 6323af7..99cbea1 100644 --- a/docs/GATEWAY_RUN.md +++ b/docs/GATEWAY_RUN.md @@ -84,49 +84,52 @@ servers: В каталоге репозитория: -```powershell +```bash docker build -t telemt-api-gateway:local . ``` ## Запуск через Docker CLI -Пример для PowerShell (подставьте путь к своему `config.yaml`): +Пример для Linux (подставьте путь к `config.yaml`; ниже — файл из текущего каталога): -```powershell -docker run -d --name telemt-gateway ` - -p 8080:8080 ` - -v "C:\path\to\config.yaml:/etc/telemt-gateway/config.yaml:ro" ` - -e CONFIG_PATH=/etc/telemt-gateway/config.yaml ` +```bash +docker run -d --name telemt-gateway \ + -p 8080:8080 \ + -v "$(pwd)/config.yaml:/etc/telemt-gateway/config.yaml:ro" \ + -e CONFIG_PATH=/etc/telemt-gateway/config.yaml \ telemt-api-gateway:local ``` Проверка: -```powershell -Invoke-WebRequest -Uri http://127.0.0.1:8080/health -UseBasicParsing -Invoke-WebRequest -Uri http://127.0.0.1:8080/api/main_srv/health -UseBasicParsing +```bash +curl -sS -i http://127.0.0.1:8080/health +curl -sS -i http://127.0.0.1:8080/api/main_srv/health ``` Второй запрос проксируется на `{base_url}/v1/health` для alias `main_srv`. Остановка и удаление: -```powershell +```bash docker stop telemt-gateway docker rm telemt-gateway ``` ## Запуск через Docker Compose -В репозитории есть [docker-compose.yml](../docker-compose.yml) и пример [config.compose.yaml](../config.compose.yaml) с `allow_all: true` и `base_url: http://host.docker.internal:9091` (Telemt на хосте). +В репозитории есть [docker-compose.yml](../docker-compose.yml) и пример [config.compose.yaml](../config.compose.yaml) с `allow_all: true` и `base_url: http://host.docker.internal:9091` (Telemt на хосте; на Docker Desktop для Linux это обычно работает из коробки). -```powershell +```bash docker compose up -d --build docker compose logs -f gateway docker compose down ``` -На старых Linux‑хостах, где нет `host.docker.internal`, замените `base_url` на IP хоста или добавьте сервис Telemt в тот же `docker-compose` и укажите его DNS‑имя. +На Linux без `host.docker.internal` сделайте одно из: + +- в `docker-compose.yml` для сервиса `gateway` добавьте `extra_hosts: ["host.docker.internal:host-gateway"]` (Docker Engine 20.10+); +- либо замените в `config.compose.yaml` значение `base_url` на IP хоста в docker‑bridge (часто `172.17.0.1`) или на имя сервиса Telemt в той же сети compose. ## Проверка @@ -143,17 +146,16 @@ docker compose down - **Образ**: пересоберите тег или подтяните новый из registry, затем `docker compose up -d --build` или `docker stop` / `docker run ...` с тем же volume конфига. - **Конфиг**: отредактируйте файл на хосте и перезапустите контейнер (шлюз не перечитывает конфиг на лету). -- **Gitea Actions**: workflow [.gitea/workflows/docker.yaml](../.gitea/workflows/docker.yaml) выполняет `go test` и собирает Docker‑образ. Для пуша в registry задайте secrets: +- **Gitea Actions**: workflow [.gitea/workflows/docker.yaml](../.gitea/workflows/docker.yaml) сначала выполняет `go mod tidy && go test ./...`, затем собирает образ через Buildx и пушит в Container Registry Gitea. - - `REGISTRY_IMAGE` — полное имя образа без тега, например `git.example.com/owner/telemt-api-gateway` - - `REGISTRY_URL` — хост registry, например `git.example.com` - - `REGISTRY_USER` / `REGISTRY_PASSWORD` - - Если secrets не заданы, образ только собирается в runner без push. + - В репозитории должен быть secret **`ACTIONS_PAT`** — personal access token пользователя с правом **`write:package`** (и при необходимости `read:package`), как для обычного `docker login` к registry. + - Логин в registry: пользователь **`gitea.actor`** (кто запустил workflow), пароль — этот PAT. + - Хост registry задаётся в workflow в `env.REGISTRY` (по умолчанию `git.shts.su`); при другом инстансе Gitea измените значение в `.gitea/workflows/docker.yaml`. + - Теги образа: `latest`, имя ветки/тега (с `/` заменённым на `-`), и `sha-<первые 12 символов коммита>`. Полный путь: `{REGISTRY}/{gitea.repository}:<тег>`. ## Устранение неполадок - **`403 forbidden` с хоста при `allow_all: false`**: добавьте CIDR клиента в `whitelist_cidrs`. Запросы из контейнера к самому себе идут с `127.0.0.1` — при необходимости добавьте `127.0.0.1/32`. - **За reverse proxy**: укажите CIDR прокси в `trusted_proxies`, иначе whitelist видит IP прокси, а не клиента. - **`502 bad_gateway`**: проверьте `base_url`, DNS в Docker‑сети и то, что Telemt слушает API (`[server.api].enabled=true` и корректный `listen`). -- **Сборка Go без Docker**: выполните `go mod tidy && go test ./...` в корне репозитория. +- **Сборка Go без Docker**: в корне репозитория выполните `go mod tidy && go test ./...`.