Compare commits
No commits in common. "d2672eb776709238bead7de2f32c206a8e3a337f" and "57fbccd4d01eae77bf831ad967a5a0b4d9f5040a" have entirely different histories.
d2672eb776
...
57fbccd4d0
44 changed files with 579 additions and 48887 deletions
12
.gitignore
vendored
12
.gitignore
vendored
|
|
@ -7,11 +7,6 @@
|
|||
# Nothing here ships; the reviewed tooling lives in provisioning/offline-repo/.
|
||||
/tmp/
|
||||
|
||||
# Python bytecode caches. Every .pyc is regenerated on import, so tracking them
|
||||
# only produces noisy diffs and a stale artifact in the checkout.
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Field OS build artifacts.
|
||||
# These are large, generated, and reproducible from a verified upstream ISO.
|
||||
|
|
@ -39,13 +34,6 @@ packages.lock.tsv
|
|||
# ...but never inside the committed bundle.
|
||||
!provisioning/offline-repo/built/
|
||||
!provisioning/offline-repo/built/**
|
||||
#
|
||||
# Except the bundle's own pool/ copy of the .deb files: those packages are
|
||||
# already tracked once under provisioning/offline-repo/packages/, and the same
|
||||
# ~890 MB does not need a second path in the repository. What the installer
|
||||
# needs from this directory is the index (Packages, Packages.gz,
|
||||
# packages.lock.tsv, SHA256SUMS) plus repo-manifest.yaml.
|
||||
provisioning/offline-repo/built/pool/
|
||||
|
||||
# Documentation site (generated)
|
||||
docs-site/node_modules/
|
||||
|
|
|
|||
16
README.md
16
README.md
|
|
@ -10,11 +10,11 @@
|
|||
|
||||
%100 ücretsiz / self-hosted Linux filo mimarisi: başka bir DevOps mühendisinin sıfırdan kurabileceği doküman setinin ve çalışan iskeletin ana reposu. Dokümanlar Türkçedir; komut, dosya, servis ve terim adları İngilizce kalır.
|
||||
|
||||
**Kurulum git tabanlıdır:** depo klonlanır, `admin/bf-bootstrap.sh` operatör araçlarını kurar ve sahada tek giriş noktası olan **grafik operatör uygulaması** `sudo bf` açılır. Uygulama Python'dur (`bfos`), Türkçedir ve terminal menüsü aynı kodun yedek arayüzüdür (`sudo bf --tui`) — grafik ekran yoksa veya tkinter kurulu değilse devreye girer. ISO/firstboot provisioning yolu (bkz. [`docs/26`](docs/26-BLUEFORCE-FIELD-OS-ISO.md), [`docs/27`](docs/27-OFFLINE-PROVISIONING.md)) **ikincil/opsiyoneldir**, silinmez. Sıfırdan başlayan için adım adım rehber: [`docs/33-OPERATOR-CONSOLE.md`](docs/33-OPERATOR-CONSOLE.md).
|
||||
**Kurulum git tabanlıdır:** depo klonlanır, `admin/bf-bootstrap.sh` operatör araçlarını kurar ve sahada tek giriş noktası olan `sudo bf-menu` kategori menüsü açılır. ISO/firstboot provisioning yolu (bkz. [`docs/26`](docs/26-BLUEFORCE-FIELD-OS-ISO.md), [`docs/27`](docs/27-OFFLINE-PROVISIONING.md)) **ikincil/opsiyoneldir**, silinmez. Sıfırdan başlayan için adım adım rehber: [`docs/33-OPERATOR-CONSOLE.md`](docs/33-OPERATOR-CONSOLE.md).
|
||||
|
||||
## Hızlı Başlangıç (git ile kurulum)
|
||||
|
||||
Kurulumun birincil yolu **git deposudur**; ISO/provisioning yolu (aşağıdaki §Kurulum Akışı, [`docs/26`](docs/26-BLUEFORCE-FIELD-OS-ISO.md)) ikincil ve opsiyoneldir. Sahadaki tek giriş noktası **`bf` operatör uygulamasıdır**: her iş ekrandan yapılır, komut ezberlenmez.
|
||||
Kurulumun birincil yolu **git deposudur**; ISO/provisioning yolu (aşağıdaki §Kurulum Akışı, [`docs/26`](docs/26-BLUEFORCE-FIELD-OS-ISO.md)) ikincil ve opsiyoneldir. Sahadaki tek giriş noktası `sudo bf-menu` **operatör konsoludur**: kategoriler numarayla seçilir, komut ezberlenmez.
|
||||
|
||||
```bash
|
||||
# 1) Depoyu indir
|
||||
|
|
@ -27,18 +27,14 @@ sudo admin/bf-bootstrap.sh
|
|||
# Depoyu klonlamadan tek satır alternatifi:
|
||||
# curl -fsSL https://raw.githubusercontent.com/emirhanmamak-blueforce/Blueforce-Linux/main/admin/bf-bootstrap.sh | sudo bash
|
||||
|
||||
# 3) Operatör uygulamasını aç (grafik arayüz)
|
||||
sudo bf
|
||||
# Grafik ekran yoksa (SSH, başsız sunucu) aynı uygulamanın terminal konsolu:
|
||||
sudo bf --tui
|
||||
# 3) Operatör konsolunu aç
|
||||
sudo bf-menu
|
||||
```
|
||||
|
||||
Uygulama açılınca **Kurulum → Bu cihazı kur** seçilir ve 8 haneli bayi no girilir (ör. `12010193` → cihaz `BF-12010193`, hostname `bf-12010193`). Kurulum sonunda cihaz `PROVISIONED_OFFLINE` olur; `READY` yalnız merkez kanalları doğrulanınca alınır.
|
||||
|
||||
**Yetki:** kurulum ve durum değiştiren işlemler yönetici yetkisi ister. `sudo bf` ile açıldığında tüm işlemler açıktır; yetkisiz açılırsa uygulama bunu başlangıçta söyler ve yalnız salt-okunur raporları çalıştırır.
|
||||
Menüden **1) Installation → 2) Install this device** seçilir ve 8 haneli bayi no girilir (ör. `12010193` → cihaz `BF-12010193`, hostname `bf-12010193`). Kurulum sonunda cihaz `PROVISIONED_OFFLINE` olur; `READY` yalnız merkez kanalları doğrulanınca alınır.
|
||||
|
||||
- Sıfırdan başlayan için adım adım rehber (hangi ekranda ne yazılır): [`docs/33-OPERATOR-CONSOLE.md`](docs/33-OPERATOR-CONSOLE.md)
|
||||
- Ekran ↔ komut eşlemesi ve kategori haritası aynı dokümanın Ek'lerindedir; özet soru-cevap: [`SUMMARY.md`](SUMMARY.md).
|
||||
- Menü ↔ komut eşlemesi ve kategori haritası aynı dokümanın Ek'lerindedir; özet soru-cevap: [`SUMMARY.md`](SUMMARY.md).
|
||||
|
||||
## Field OS Nedir?
|
||||
|
||||
|
|
|
|||
33
SUMMARY.md
33
SUMMARY.md
|
|
@ -11,10 +11,10 @@
|
|||
## 1. Field OS için Kısa Soru-Cevap (2026-09-16 turu)
|
||||
|
||||
- **Blueforce Field OS nedir?** — Ubuntu Server 26.04.1+ LTS üzerinde maintain edilen GNOME katmanı bulunan, çevrimdışı kurulabilen, merkezden yönetilen; onaysız güncelleme yapmayan ve 4 uzak erişim kanalı kullanan **endüstriyel saha işletim sistemi standardıdır**. Üç parçası vardır: zemin (Ubuntu LTS + GNOME + terminale boot), provisioning (tek kurucu + autoinstall/offline APT/firstboot + tek USB Field OS ISO) ve işletme (WireGuard + 4 kanal + Docker/MEG + monitoring + Ansible/Semaphore). **Medya tabanı sapması:** kanonik baseline Ubuntu **Server**'dır; build host'ta checksum'ı doğrulanmış tek medya Ubuntu **Desktop** ISO olduğu için üretilen ilk ISO Desktop tabanlıdır (manifest `baseline_deviation` bloğu). Hedef işletim sistemi yine Server paket setidir (`ubuntu-server` + `ubuntu-desktop-minimal` + GNOME, terminale boot); sapma yalnız medya tabanındadır ve LAB kararı bekler. → [`00`](docs/00-MASTER-PLAN.md), [`01`](docs/01-ARCHITECTURE.md), [`26`](docs/26-BLUEFORCE-FIELD-OS-ISO.md), [`31`](docs/31-LEARNING-GUIDE.md) (K-01, K-02, K-20)
|
||||
- **Nasıl kurulur?** — Kurulumun birincil yolu **git deposudur**: `git clone https://github.com/emirhanmamak-blueforce/Blueforce-Linux.git` → `cd Blueforce-Linux` → `sudo admin/bf-bootstrap.sh` (depoyu klonlamadan tek satır alternatifi: `curl -fsSL https://raw.githubusercontent.com/emirhanmamak-blueforce/Blueforce-Linux/main/admin/bf-bootstrap.sh | sudo bash`) → **`sudo bf`** (grafik operatör uygulaması) → `Kurulum` sekmesi → **"Bu cihazı kur"** → 8 haneli bayi no → onay. Bootstrap yalnız operatör araçlarını ve `bf-*` komutlarını kurar; **cihaz kimliği (bayi no) İSTEMEZ**, disk bölmez, veri silmez, onaysız güncelleme yapmaz (idempotent). **Kurulum internetsizdir:** paketler depoyla gelir (`provisioning/offline-repo/packages/`, 1321 `.deb`, ~888 MB, Git LFS) ve kuran kişi hiçbir şey indirmez; kurucu yerel paket deposunu kendi bulur (`--offline` gerekmez). Grafik ekran veya `python3-tk` yoksa uygulama Türkçe yönlendirme yapıp **`sudo bf --tui`** terminal konsolunu önerir (çıkış kodu 3). ISO/firstboot yolu ([`26`](docs/26-BLUEFORCE-FIELD-OS-ISO.md)/[`27`](docs/27-OFFLINE-PROVISIONING.md)) **ikincil/opsiyoneldir** ve silinmez. Ayrıntılı adım adım rehber: [`33`](docs/33-OPERATOR-CONSOLE.md). → [`05`](docs/05-ONE-CLICK-INSTALLER.md), [`33`](docs/33-OPERATOR-CONSOLE.md) (K-09, K-12, K-20)
|
||||
- **Arayüz nasıl kullanılır?** — Sahadaki tek giriş noktası **grafik operatör uygulamasıdır**: `sudo bf` (Python paketi `bfos`, Tkinter arayüzü `bfos/ui_gui.py`); pencere başlığı `Blueforce Field OS — Yönetim`. Basit modda üç düğme vardır (`Kur`, `Durum`, `Çıkış`); **`Detaylı mod`** ile 5 sekme açılır: `Kurulum`, `Cihaz işlemleri`, `Merkez hazırlığı`, `Araçlar`, `Cihaz bilgisi`. Hedef üst çubuktan seçilir: **Bayi no (8 hane)** (`^[0-9]{8}$` doğrulamalı) veya dalga grubu (lab, pilot_1, pilot_2, wave_1, wave_2, production); geçersiz format komut üretmez (K-12). Her komut çalıştırılmadan önce ekranda gösterilir ve onay istenir; yıkıcı işlemler iki kez sorar; production kapsamı için ek onay (ve `production` yazma) gerekir (K-11). Grafik ekran yoksa (SSH/başsız oturum) veya `python3-tk` kurulu değilse uygulama Türkçe hata verip **`sudo bf --tui`** terminal konsolunu önerir (çıkış kodu 3); eski bash menü `sudo admin/bf-menu` yalnız **yedek**tir, ana yol değildir. `sudo bf` = tam yetki; root değilse uygulama başlangıçta uyarır ve yalnız salt-okunur raporları çalıştırır (yazma işlemleri çalıştırma katmanında da reddedilir). Onaysız güncelleme seçeneği **yoktur**; `bf-gui-*` yalnız **yerel fiziksel** ekranı açar/kapatır, RDP (xrdp/xrdp-sesman) her zaman hazırdır (K-22). Şifre üretimi opsiyoneldir ve **varsayılan kapalıdır** (`bf-creds --generate`; parola ekrana/loga gitmez). Denetim log'u `/var/log/blueforce-console.log` (mod `600`). → [`33`](docs/33-OPERATOR-CONSOLE.md), [`05`](docs/05-ONE-CLICK-INSTALLER.md), [`09`](docs/09-FLEET-MANAGEMENT.md), [`10`](docs/10-UPDATE-AND-ROLLBACK-POLICY.md) (K-11, K-13, K-22)
|
||||
- **Nasıl kurulur?** — Kurulumun birincil yolu **git deposudur**: `git clone https://github.com/emirhanmamak-blueforce/Blueforce-Linux.git` → `cd Blueforce-Linux` → `sudo admin/bf-bootstrap.sh` (depoyu klonlamadan tek satır alternatifi: `curl -fsSL https://raw.githubusercontent.com/emirhanmamak-blueforce/Blueforce-Linux/main/admin/bf-bootstrap.sh | sudo bash`) → `sudo bf-menu`. Bootstrap yalnız operatör araçlarını ve `bf-*` komutlarını kurar; **cihaz kimliği (bayi no) İSTEMEZ**, disk bölmez, veri silmez, onaysız güncelleme yapmaz (idempotent). Kimlik ilk `bf-menu` seansında girilir. ISO/firstboot yolu ([`26`](docs/26-BLUEFORCE-FIELD-OS-ISO.md)/[`27`](docs/27-OFFLINE-PROVISIONING.md)) **ikincil/opsiyoneldir** ve silinmez. Ayrıntılı adım adım rehber: [`33`](docs/33-OPERATOR-CONSOLE.md). → [`05`](docs/05-ONE-CLICK-INSTALLER.md), [`33`](docs/33-OPERATOR-CONSOLE.md) (K-09, K-12, K-20)
|
||||
- **Menü nasıl kullanılır?** — Sahadaki tek giriş noktası `sudo bf-menu` **operatör konsoludur**: 5 kategori numarayla seçilir, komut ezberlenmez (**1** Installation, **2** Device operations, **3** Central (preparation), **4** Tools, **5** Device information; ana ekranda `q` = çıkış, alt menülerde `0` = geri). Her komut çalıştırılmadan önce ekranda gösterilir ve onay istenir; yıkıcı işlemler iki kez sorar. Kurulumda "**Dealer number (8 digits)**" sorulur (ör. `12010193` → `BF-12010193` / `bf-12010193`); geçersiz format kurulumu başlatmaz (K-12). Filo işlemleri (kategori 2) hedefi **tek cihaz (bayi no) / grup-dalga (lab, pilot_1, pilot_2, wave_1, wave_2, production) / tüm filo** olarak seçtirir; wave-scoped playbook'ta "tüm filo" dalga dalga ilerler ve her dalga ayrı onaylanır, production için `production` yazmak zorunludur (K-11). Onaysız güncelleme seçeneği **yoktur**; `bf-gui-*` yalnız **yerel fiziksel** ekranı açar/kapatır, RDP (xrdp/xrdp-sesman) her zaman hazırdır (K-22). Şifre üretimi opsiyoneldir ve **varsayılan kapalıdır** (`bf-creds --generate`; parola ekrana/loga gitmez). Denetim log'u `/var/log/blueforce-console.log` (mod `600`). → [`33`](docs/33-OPERATOR-CONSOLE.md), [`09`](docs/09-FLEET-MANAGEMENT.md), [`10`](docs/10-UPDATE-AND-ROLLBACK-POLICY.md) (K-11, K-13, K-22)
|
||||
- **ISO nasıl build edilir?** — Autoinstall kurulum **motorudur**, Blueforce Field OS ISO ise **paketleme/dağıtım** yöntemidir; ikisi rakip değil, birlikte kullanılır. `provisioning/iso/build-blueforce-iso.sh --upstream-iso <BASE> --checksum-file <SHA256SUMS>` çalıştırılır; builder base ISO'yu doğrular, ağacı çıkarır, autoinstall + firstboot + offline-repo araçlarını ekler, GRUB satırlarına autoinstall yazar ve boot düzenini base ISO'nun kendi `as_mkisofs` reçetesinden yeniden kurar. **ISO üretilmiştir:** `dist/Blueforce-Field-OS-1.0.0-amd64.iso` (6 481 917 952 byte, SHA256 `cb0cc56f…d431296`), El Torito BIOS+UEFI korunmuş, `/autoinstall.yaml` medya kökünde. Boot kabulü (UEFI/Legacy/Secure Boot) ve air-gapped kurulum hâlâ LAB işidir; resmi Ubuntu ISO + NoCloud seed USB yedek/geri dönüş yoludur. → [`26`](docs/26-BLUEFORCE-FIELD-OS-ISO.md), [`32`](docs/32-REPOSITORY-AUDIT-AND-CONFLICTS.md) (K-15, K-20)
|
||||
- **Offline kurulum nasıl çalışır?** — Paketler **git deposunda taşınır** (`provisioning/offline-repo/packages/`, 1321 `.deb`, ~888 MB, Git LFS ile takip edilir) ve kuran kişi **hiçbir şey indirmez**: `sudo bf` → Kurulum sekmesi → "Bu cihazı kur" akışı internetsiz çalışır. Kurucu yerel paket deposunu **kendi bulur** (sıra: `BF_OFFLINE_REPO` → `<repo>/provisioning/offline-repo/built` → `/opt/blueforce/offline-repo`); `--offline` bayrağı **zorunlu değildir**, yalnız yerel depoyu zorlar. İki hata durumu vardır ve ikisinde de paket adımlarına geçilmez, sistemde hiçbir değişiklik yapılmaz: depo hiç yoksa aranan yollar + `ÇIKIŞ NEDENİ: yerel paket deposu bulunamadı.` (exit 1); depo bozuksa `OFFLINE BLOCKED: <sebep>` (exit 1). Grafik arayüzün gerektirdiği `python3-tk` paketi de offline depoda pinlidir. Sonuç `PROVISIONED_OFFLINE`'dır. → [`27`](docs/27-OFFLINE-PROVISIONING.md), [`05`](docs/05-ONE-CLICK-INSTALLER.md), [`31`](docs/31-LEARNING-GUIDE.md) (K-16, K-20, K-21)
|
||||
- **Offline kurulum nasıl çalışır?** — Sürümlü medya + offline APT snapshot kullanılır; `blueforce-install.sh --offline` yalnız yerel `file:` APT kaynağından paket kurar (uzak indirme, key download, `apt download` yok) ve kurulum `PROVISIONED_OFFLINE` durumuna gelir. Subiquity'nin `apt.fallback` varsayılanı zaten `offline-install`'dır. Medya manifestlerinde somut `package=version` pinleri yoksa kurucu `OFFLINE BLOCKED` ile durur — "offline olur" demek için paket seti gerçekten dolu olmalıdır. → [`27`](docs/27-OFFLINE-PROVISIONING.md), [`31`](docs/31-LEARNING-GUIDE.md) (K-16, K-20, K-21)
|
||||
- **Device state'leri nedir?** — Üç durum, tek sıra: `PROVISIONED_OFFLINE` → `ENROLLED` → `READY`. Tek kaynak `/var/lib/blueforce/state.json`, okuma komutu `bf-enrollment-status`. `READY` **tek durum değildir**: "kuruldu" READY değildir, "token alındı" READY değildir; yalnız WireGuard + merkezi remote + monitoring kanıtı doğrulanınca READY yazılır ve `bf-check-ready` bu kanıtı her seferinde yeniden denetler. → [`27`](docs/27-OFFLINE-PROVISIONING.md), [`29`](docs/29-DEVICE-ENROLLMENT.md) (K-16, K-17, K-21)
|
||||
- **Internet olmadan ne olur?** — Yerel kurulum tamamlanır: paketler offline snapshot'tan gelir, cihaz `PROVISIONED_OFFLINE` olur. Cihaz çalışır ama merkezce doğrulanmamıştır: uzaktan erişim/izleme kanalları ve READY kapısı kapalı kalır. Yerel GUI kapalıyken bile xRDP servisi ayaktadır; ancak WireGuard tüneli olmadığı için merkezden erişilemez. → [`27`](docs/27-OFFLINE-PROVISIONING.md) (K-16, K-21, K-22)
|
||||
- **Internet gelince ne olur?** — Merkezi admin, `BF-<no>`'ya bağlı kısa ömürlü ve tek kullanımlık token üretir; teknisyen tokenı yalnız cihaz ekranına girer (`bf-enroll --token-stdin`). Token tüketilince WireGuard yapılandırması atomik kurulur ve durum `ENROLLED` olur. Ardından güncel WG handshake, xRDP/RustDesk yapılandırması ve merkezi `monitoring`/`remote`/`management` kanıtı doğrulanınca `READY` yazılır; kanıt `pending` ya da eksikse cihaz ENROLLED'da kalır (fail-closed). → [`29`](docs/29-DEVICE-ENROLLMENT.md) (K-17, K-21)
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
- **Field OS version nasıl takip edilir?** — Cihazda `bf-release` komutu okunur; kaynak sırası `BF_RELEASE_MANIFEST` → `/etc/blueforce/release-manifest.yaml` → legacy `/etc/blueforce-release` → repo manifesti. Manifest `status: skeleton` ise komut `UNAPPROVED_SKELETON` yazar ve **exit≠0** verir: iskelet medya dağıtılabilir release sayılmaz. Gerçek sürüm kimliği immutable release manifestiyle (ISO/seed/offline APT snapshot/installer/Ansible commit + checksum) eşleşir. → [`30`](docs/30-FIELD-OS-RELEASE-MANAGEMENT.md) (K-18, K-24)
|
||||
- **Operatör hangi rehberden öğrenir?** — Linux, ağ, otomasyon, ISO, enrollment ve rollback pratikleri yalnız LAB'da [`31`](docs/31-LEARNING-GUIDE.md) ile çalışılır; komutlar örnektir ve LAB doğrulaması gerektirir.
|
||||
|
||||
Bu 12 soru + öğrenme rehberi sorusu, karar günlüğünde S-28…S-37 olarak izlenir ([Ek B-2](docs/24-DECISION-LOG.md)); bu tura `docs/33` ile **"Nasıl kurulur?"** ve **"Arayüz nasıl kullanılır?"** soruları eklendi (yukarıdaki ilk bloğun devamı); kurulum ve arayüz anlatımı grafik operatör uygulaması (`sudo bf`) üzerinedir, terminal yolu yedektir.
|
||||
Bu 12 soru + öğrenme rehberi sorusu, karar günlüğünde S-28…S-37 olarak izlenir ([Ek B-2](docs/24-DECISION-LOG.md)); bu tura `docs/33` ile **"Nasıl kurulur?"** ve **"Menü nasıl kullanılır?"** soruları eklendi (yukarıdaki ilk bloğun devamı).
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -47,16 +47,13 @@ Bu 12 soru + öğrenme rehberi sorusu, karar günlüğünde S-28…S-37 olarak i
|
|||
Ansible, Prometheus, log, envanter, runbook) join anahtarıdır. Örn. `BF-12010193` / `bf-12010193`. → [`02`](docs/02-DEVICE-NAMING-AND-INVENTORY.md) (K-12)
|
||||
6. **İlk PC hazırlığı nasıl?** — İmaj dondurulmadan **önce** `bf-hardware-inventory.sh` ile donanım
|
||||
taraması (CPU/RAM/disk/NIC/GPU profilleri) ve Windows keşfi (F0); profilsiz imaj sahada rastgele kırılır. → [`18`](docs/18-PILOT-AND-700-DEVICE-ROLLOUT.md), [`28`](docs/28-WINDOWS-TO-LINUX-MIGRATION.md) (K-09, K-19)
|
||||
7. **Yeni PC kurulumu kaç adım?** — Teknisyen için akış: USB medyasıyla Ubuntu kur → depo kopyasını getir
|
||||
→ `sudo bf` → Hedef: bayi no → Kurulum → "Bu cihazı kur" (8 haneli bayi no) → durumda `PROVISIONED_OFFLINE` gör →
|
||||
internet geldiğinde enrollment ve merkezi kontrolleri tamamla; yalnız sonra `READY` teslim edilir.
|
||||
Paketler depoyla geldiği için kurulumda **indirme yapılmaz**. →
|
||||
[`05`](docs/05-ONE-CLICK-INSTALLER.md), [`27`](docs/27-OFFLINE-PROVISIONING.md), [`29`](docs/29-DEVICE-ENROLLMENT.md), [`20`](docs/20-FIELD-TECHNICIAN-RUNBOOK.md) (K-16, K-17, K-21)
|
||||
8. **Installer nasıl çalışacak?** — Tek giriş grafik operatör uygulamasıdır (`sudo bf` → `Kurulum` sekmesi →
|
||||
"Bu cihazı kur"); bu düğme `blueforce-install.sh --dealer-id <8hane>` motorunu çağırır ve paket deposunu
|
||||
otomatik bulur (`--offline` zorunlu değil). Yedek yol `sudo bf --tui`, acil yedek bash menü `sudo admin/bf-menu`.
|
||||
Kurucu yalnız `PROVISIONED_OFFLINE` yazar. `READY`, installer çıkış kodu değil enrollment sonrası merkezi
|
||||
WireGuard, erişim ve monitoring doğrulamasının sonucudur. →
|
||||
7. **Yeni PC kurulumu kaç adım?** — Teknisyen için akış: USB medyasıyla Ubuntu kur →
|
||||
`blueforce-install.sh --offline` + 8 haneli bayi no → `bf-status` ile `PROVISIONED_OFFLINE` gör →
|
||||
internet geldiğinde enrollment ve merkezi kontrolleri tamamla; yalnız sonra `READY` teslim edilir. →
|
||||
[`27`](docs/27-OFFLINE-PROVISIONING.md), [`29`](docs/29-DEVICE-ENROLLMENT.md), [`20`](docs/20-FIELD-TECHNICIAN-RUNBOOK.md) (K-16, K-17, K-21)
|
||||
8. **Installer nasıl çalışacak?** — Tek giriş `blueforce-install.sh --dealer-id <8hane>`; çevrimdışı yol
|
||||
`--offline` ile yerel medya/snapshot kullanır ve yalnız `PROVISIONED_OFFLINE` yazar. `READY`, installer
|
||||
çıkış kodu değil enrollment sonrası merkezi WireGuard, erişim ve monitoring doğrulamasının sonucudur. →
|
||||
[`05`](docs/05-ONE-CLICK-INSTALLER.md), [`27`](docs/27-OFFLINE-PROVISIONING.md), [`29`](docs/29-DEVICE-ENROLLMENT.md) (K-21)
|
||||
9. **WireGuard mimarisi?** — **Hub-spoke**: merkez hub (`10.8.0.1`), her cihaz spoke (peer adı `bf-<no>`,
|
||||
sabit `/32`); istemcide `PersistentKeepalive = 25` + `wg-quick@wg0` enable; SSH/RDP yalnızca tünel
|
||||
|
|
@ -174,7 +171,7 @@ kaynak URL'ler [`24 Ek A`](docs/24-DECISION-LOG.md).
|
|||
## Ek: QA Doğrulama (2026-09-16 güncellemesi)
|
||||
|
||||
- **33 numaralı doküman mevcut:** `docs/00` … `docs/32` (+ `docs/_TEMPLATE.md`); kanonik set `00`–`31`, `32` denetim/çelişki raporudur.
|
||||
- **Ek (operatör konsolu):** `docs/33-OPERATOR-CONSOLE.md` eklendi (§1–§13 + Mermaid; git kurulumu + grafik operatör arayüzü (`sudo bf`) ve `sudo bf --tui` yedek konsolu rehberi). Numaralı set artık `docs/00` … `docs/33` (34 dosya).
|
||||
- **Ek (operatör konsolu):** `docs/33-OPERATOR-CONSOLE.md` eklendi (§1–§13 + Mermaid; git kurulumu + `bf-menu` menü rehberi). Numaralı set artık `docs/00` … `docs/33` (34 dosya).
|
||||
- **13 başlık:** 33 dosyanın tamamında §1–§13 sıralı ve eksiksiz (bu turda `docs/32` §1–§13 yapısına getirildi).
|
||||
- **Mermaid:** 33/33 dosyada ≥1 diyagram; toplam 35 blok (30 dosyada 1, birkaçında 2+).
|
||||
- **BF-/bf- tutarlılığı:** insan arayüzü `BF-<no>`, makine adı `bf-<no>`; aykırı kullanım yok (kalan `BF-xxxx`/`BF-no` ifadeleri şablon yer tutucudur).
|
||||
|
|
@ -188,7 +185,5 @@ kaynak URL'ler [`24 Ek A`](docs/24-DECISION-LOG.md).
|
|||
`check-provisioning-static.sh`, `test-firstboot-static.sh` **GEÇTİ**; `check-specs.sh` iki **bayat sabit** nedeniyle düşer
|
||||
(kanonik doküman sayısı `32`→`33`, Mermaid toplamı `34`→`35`); `test-field-os-lifecycle.sh` **kırmızı** (READY/durum sözleşmesi).
|
||||
Düzeltmeler `tests/` ve ilgili provisioning akışı kapsamındadır — ayrıntı [`docs/32 §10`](docs/32-REPOSITORY-AUDIT-AND-CONFLICTS.md).
|
||||
- **Üretim artefaktı:** `*.deb` havuzu artık repoda: `provisioning/offline-repo/packages/` altında 1321 paket (~888 MB, Git LFS),
|
||||
pin manifestolarında `UNPINNED` sentinel kalmadı ve `python3-tk` (grafik arayüz) dahil pinlendi. Ancak kurucunun aradığı `built/` bundle dizini
|
||||
(Packages, Packages.gz, packages.lock.tsv, SHA256SUMS, pool/) bu checkout'ta **yok**; bu haliyle kurulum "yerel paket deposu yok" diyerek fail-closed durur,
|
||||
repo sorumlusunun `build-index.sh` koşup `built/` dizinini commit'lemesi gerekir. Merkezi enrollment endpoint'i yok; air-gapped kurulum ve ISO boot kabulü LAB işidir.
|
||||
- **Üretim artefaktı:** henüz `*.iso` yok, `*.deb` havuzu yok, offline pinler `UNPINNED` sentinel, `packages.lock.tsv` yok,
|
||||
merkezi enrollment endpoint'i yok. Yani "offline kurulum çalışıyor" bugün **kanıtlanmış değildir**; F2A/F2B kapıları açıktır.
|
||||
|
|
|
|||
BIN
bfos/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
bfos/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
bfos/__pycache__/cli.cpython-311.pyc
Normal file
BIN
bfos/__pycache__/cli.cpython-311.pyc
Normal file
Binary file not shown.
BIN
bfos/__pycache__/config.cpython-311.pyc
Normal file
BIN
bfos/__pycache__/config.cpython-311.pyc
Normal file
Binary file not shown.
BIN
bfos/__pycache__/operations.cpython-311.pyc
Normal file
BIN
bfos/__pycache__/operations.cpython-311.pyc
Normal file
Binary file not shown.
BIN
bfos/__pycache__/runner.cpython-311.pyc
Normal file
BIN
bfos/__pycache__/runner.cpython-311.pyc
Normal file
Binary file not shown.
BIN
bfos/__pycache__/tui.cpython-311.pyc
Normal file
BIN
bfos/__pycache__/tui.cpython-311.pyc
Normal file
Binary file not shown.
BIN
bfos/__pycache__/ui_gui.cpython-311.pyc
Normal file
BIN
bfos/__pycache__/ui_gui.cpython-311.pyc
Normal file
Binary file not shown.
44
bfos/cli.py
44
bfos/cli.py
|
|
@ -62,10 +62,6 @@ def build_parser() -> argparse.ArgumentParser:
|
|||
)
|
||||
parser.add_argument("-h", "--help", action="help", help="bu yardımı göster ve çık")
|
||||
parser.add_argument("-V", "--version", action="store_true", help="sürümü göster ve çık")
|
||||
parser.add_argument("--gui", action="store_true",
|
||||
help="grafik arayüzü aç (varsayılan davranış)")
|
||||
parser.add_argument("--tui", action="store_true",
|
||||
help="terminal konsolunu aç (grafik arayüz açılamıyorsa yedek)")
|
||||
parser.add_argument("--full", action="store_true",
|
||||
help="detaylı mod: tüm kategoriler ve 21 playbook görünür")
|
||||
parser.add_argument("--dry-run", action="store_true",
|
||||
|
|
@ -1014,33 +1010,10 @@ def catalogue_lines() -> List[str]:
|
|||
# ---------------------------------------------------------------------------
|
||||
# Entry point
|
||||
# ---------------------------------------------------------------------------
|
||||
def _wants_tui(args: argparse.Namespace) -> bool:
|
||||
"""Whether this invocation belongs to the terminal console.
|
||||
|
||||
The GUI is the default. A few flags exist only in the terminal console --
|
||||
they print text and exit, or tune terminal rendering -- so an invocation
|
||||
carrying one of them must stay there instead of being swallowed by the
|
||||
router. ``--tui`` forces it explicitly.
|
||||
"""
|
||||
if args.tui:
|
||||
return True
|
||||
if args.gui:
|
||||
return False
|
||||
# --list prints a text catalogue (the TUI's report format) and exits; it is
|
||||
# a report, not an interactive surface, so it stays in the terminal console.
|
||||
return bool(args.list or args.check or args.list_targets or args.no_color
|
||||
or args.log_file != config.DEFAULT_LOG_FILE
|
||||
or args.lang != config.DEFAULT_LANG)
|
||||
|
||||
|
||||
def main(argv: Optional[Sequence[str]] = None) -> int:
|
||||
parser = build_parser()
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
if args.tui and args.gui:
|
||||
sys.stderr.write("HATA: --tui ve --gui birlikte kullanılamaz.\n")
|
||||
return config.EXIT_USAGE
|
||||
|
||||
if args.version:
|
||||
sys.stdout.write("{0} {1}\n".format(config.PROGRAM_NAME, config.VERSION))
|
||||
return config.EXIT_OK
|
||||
|
|
@ -1050,23 +1023,6 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
|
|||
value=args.lang, supported=", ".join(config.SUPPORTED_LANGS)) + "\n")
|
||||
return config.EXIT_USAGE
|
||||
|
||||
if not _wants_tui(args):
|
||||
# Imported lazily: the GUI pulls in tkinter, and the terminal console
|
||||
# must keep working on a device where that import is unavailable.
|
||||
from . import ui_gui
|
||||
gui_argv: List[str] = []
|
||||
if args.full:
|
||||
gui_argv.append("--full")
|
||||
if args.dry_run:
|
||||
gui_argv.append("--dry-run")
|
||||
if args.repo:
|
||||
gui_argv.extend(["--repo", args.repo])
|
||||
if args.inventory:
|
||||
gui_argv.extend(["--inventory", args.inventory])
|
||||
if args.list:
|
||||
gui_argv.append("--list")
|
||||
return ui_gui.main(gui_argv)
|
||||
|
||||
try:
|
||||
repo = resolve_repo(args.repo)
|
||||
except Refused as exc:
|
||||
|
|
|
|||
|
|
@ -325,10 +325,6 @@ MSG_COMMAND_TITLE = "Çalıştırılacak komut"
|
|||
MSG_RUN_ASK = "Bu komut çalıştırılsın mı? [y=çalıştır / c=--check ile çalıştır / N=iptal]: "
|
||||
MSG_DESTRUCTIVE_WARN = "DURUM DEĞİŞTİREN İŞLEM: {label}"
|
||||
MSG_DESTRUCTIVE_SUB = "Onaylamadan önce yukarıdaki komutu okuyun; seçilen cihazları değiştirir."
|
||||
MSG_ROOT_REQUIRED = (
|
||||
"Bu işlem BU cihazda root yetkisi gerektirir.\n"
|
||||
"Konsolu tekrar sudo ile başlatın: sudo bf"
|
||||
)
|
||||
MSG_DESTRUCTIVE_GATE = (
|
||||
"Yıkıcı işlem kapısı: {label} seçilen cihazları değiştirir. "
|
||||
"Bu onaydan sonra komut üretilir ve çalıştırmadan önce ayrıca sorulur."
|
||||
|
|
|
|||
|
|
@ -276,11 +276,6 @@ class Runner:
|
|||
self.audit.write(config.AUDIT_CANCEL, "operatör iptal etti :: " + command_string(argv))
|
||||
return RunResult(argv=list(argv), cancelled=True)
|
||||
|
||||
# NOTE: this method does not enforce root. The terminal console gates a
|
||||
# destructive operation earlier (App.require_root, config.MSG_ROOT_REQUIRED)
|
||||
# and the GUI gates it at its execution choke point (ui_gui.run_plan).
|
||||
# Enforcing here as well double-guarded the same rule and fired before
|
||||
# the console's own message, so the operator saw the wrong explanation.
|
||||
self.audit.write(config.AUDIT_RUN, command_string(final))
|
||||
result = self._spawn_exit_code(final)
|
||||
result.check = "--check" in final
|
||||
|
|
|
|||
106
bfos/ui_gui.py
106
bfos/ui_gui.py
|
|
@ -194,10 +194,7 @@ PLAYBOOK_DIR_REL = "ansible/playbooks"
|
|||
MENU_REL = "admin/bf-menu"
|
||||
|
||||
TK_PACKAGE_HINT = "sudo apt install -y python3-tk"
|
||||
# Grafik arayüz açılamadığında kullanılacak yol: aynı bfos uygulamasının
|
||||
# terminal konsolu. Bash menü (bf-menu) hâlâ yedek olarak durur ama Python
|
||||
# konsolu ana yoldur, o yüzden önce o önerilir.
|
||||
TERMINAL_MENU_HINT = "sudo bf --tui"
|
||||
TERMINAL_MENU_HINT = "sudo bf-menu"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# tkinter -- opsiyonel ice aktarma
|
||||
|
|
@ -260,19 +257,9 @@ class Operation:
|
|||
description: str = ""
|
||||
playbook: str = ""
|
||||
options: tuple[OptionSpec, ...] = ()
|
||||
# None means "not stated": the value is then derived from `destructive` by
|
||||
# the property below, so a write operation cannot be marked read-only by
|
||||
# omission. An operation that genuinely differs states the value.
|
||||
requires_root: bool | None = None
|
||||
requires_root: bool = False
|
||||
needs_dealer: bool = False
|
||||
|
||||
@property
|
||||
def needs_root(self) -> bool:
|
||||
"""Whether this operation must run as root to be allowed."""
|
||||
if self.requires_root is None:
|
||||
return bool(self.destructive)
|
||||
return bool(self.requires_root)
|
||||
|
||||
@property
|
||||
def is_fleet(self) -> bool:
|
||||
return self.scope in ("simple", "wave", "release")
|
||||
|
|
@ -331,7 +318,7 @@ class CommandPlan:
|
|||
|
||||
commands: tuple[tuple[str, ...], ...] = ()
|
||||
destructive: bool = False
|
||||
requires_root: bool | None = None
|
||||
requires_root: bool = False
|
||||
operation_id: str = ""
|
||||
target_label: str = ""
|
||||
notes: tuple[str, ...] = ()
|
||||
|
|
@ -339,13 +326,6 @@ class CommandPlan:
|
|||
dry_run: bool = False
|
||||
check_mode: bool = False
|
||||
|
||||
@property
|
||||
def needs_root(self) -> bool:
|
||||
"""Whether running this plan requires root (derived when not stated)."""
|
||||
if self.requires_root is None:
|
||||
return bool(self.destructive)
|
||||
return bool(self.requires_root)
|
||||
|
||||
@property
|
||||
def lines(self) -> tuple[str, ...]:
|
||||
"""Kopyala/yapistir edilebilir komut satirlari (bf-menu %q ile ayni fikir)."""
|
||||
|
|
@ -600,7 +580,7 @@ def preview_text(
|
|||
parts.append(f"Hedef : {target.label}")
|
||||
elif plan.target_label:
|
||||
parts.append(f"Hedef : {plan.target_label}")
|
||||
if plan.needs_root:
|
||||
if plan.requires_root:
|
||||
parts.append("Yetki : root gerekir — konsolu sudo ile açın.")
|
||||
if plan.check_mode:
|
||||
parts.append("Kip : --check (deneme) — hiçbir değişiklik uygulanmaz.")
|
||||
|
|
@ -1093,12 +1073,6 @@ def run_plan(
|
|||
for line in plan.lines:
|
||||
emit(f"[deneme] {line}")
|
||||
return RunResult(0, True, "[deneme] komut çalıştırılmadı.\n")
|
||||
if plan.needs_root and not write_operations_enabled():
|
||||
# Last line of defence: every execution path funnels through this
|
||||
# function, so the root rule holds even if a future caller builds the
|
||||
# plan itself instead of going through the GUI's run button.
|
||||
emit("[ENGELLENDİ] " + NON_ROOT_DISABLED_HINT)
|
||||
return RunResult(2, False, NON_ROOT_DISABLED_HINT + "\n")
|
||||
|
||||
chunks: list[str] = []
|
||||
for index, argv in enumerate(plan.commands, start=1):
|
||||
|
|
@ -1437,7 +1411,7 @@ class CatalogueBackend:
|
|||
return CommandPlan(
|
||||
commands=(tuple(argv),),
|
||||
destructive=operation.destructive,
|
||||
requires_root=operation.needs_root,
|
||||
requires_root=operation.requires_root,
|
||||
operation_id=operation.id,
|
||||
target_label=target.label + (f" (dalga {wave})" if wave else ""),
|
||||
notes=tuple(notes),
|
||||
|
|
@ -1680,7 +1654,7 @@ class CatalogueBackend:
|
|||
return CommandPlan(
|
||||
commands=tuple(commands),
|
||||
destructive=operation.destructive,
|
||||
requires_root=operation.needs_root,
|
||||
requires_root=operation.requires_root,
|
||||
operation_id=operation.id,
|
||||
target_label=label,
|
||||
notes=tuple(notes),
|
||||
|
|
@ -1827,30 +1801,18 @@ class ModuleBackend:
|
|||
category = get("category") or "Cihaz işlemleri"
|
||||
if category not in CATEGORIES:
|
||||
category = "Cihaz işlemleri"
|
||||
scope = str(get("scope") or get("declared_scope") or "simple")
|
||||
scope = get("scope") or get("declared_scope") or "simple"
|
||||
prompt = get("prompt") or "none"
|
||||
destructive = bool(get("destructive") or get("is_destructive") or False)
|
||||
# requires_root is left None unless the source actually states it, so the
|
||||
# Operation property derives it from `destructive`. Reading the field
|
||||
# with a False default marked every real operation read-only and the
|
||||
# root gate never fired; the catalogue's `destructive` flag is the
|
||||
# honest signal. An operation that states the value keeps that answer.
|
||||
stated_root = None
|
||||
if isinstance(item, dict):
|
||||
if "requires_root" in item:
|
||||
stated_root = bool(item["requires_root"])
|
||||
elif getattr(item, "requires_root", None) is not None:
|
||||
stated_root = bool(item.requires_root)
|
||||
return Operation(
|
||||
id=str(op_id),
|
||||
label=str(label),
|
||||
category=str(category),
|
||||
destructive=destructive,
|
||||
scope=scope,
|
||||
destructive=bool(get("destructive") or get("is_destructive") or False),
|
||||
scope=str(scope),
|
||||
description=str(get("description") or ""),
|
||||
playbook=str(get("playbook") or ""),
|
||||
options=_prompt_options(str(prompt)),
|
||||
requires_root=stated_root,
|
||||
requires_root=bool(get("requires_root") or False),
|
||||
needs_dealer=bool(get("needs_dealer") or False),
|
||||
)
|
||||
|
||||
|
|
@ -2107,7 +2069,7 @@ class ModuleBackend:
|
|||
return CommandPlan(
|
||||
commands=(tuple(argv),),
|
||||
destructive=operation.destructive,
|
||||
requires_root=operation.needs_root,
|
||||
requires_root=operation.requires_root,
|
||||
operation_id=operation.id,
|
||||
target_label=f"cihaz {dealer_to_device_id(dealer)} ({dealer_to_host(dealer)})",
|
||||
notes=tuple(notes),
|
||||
|
|
@ -2138,7 +2100,7 @@ class ModuleBackend:
|
|||
return CommandPlan(
|
||||
commands=(tuple(argv),),
|
||||
destructive=operation.destructive,
|
||||
requires_root=operation.needs_root,
|
||||
requires_root=operation.requires_root,
|
||||
operation_id=operation.id,
|
||||
target_label="bu cihaz (yerel)",
|
||||
notes=tuple(notes),
|
||||
|
|
@ -2504,14 +2466,6 @@ class BfGui: # pragma: no cover - pencere gerektirir (statik testler dokunmaz)
|
|||
text="DENEME KİPİ (--dry-run): komutlar gösterilir, çalıştırılmaz.",
|
||||
foreground="#a05000",
|
||||
).pack(anchor="w")
|
||||
if not is_root():
|
||||
# Söylenmezse operatör kurulumu başlatır ve yarı yolda yetki
|
||||
# hatasıyla karşılaşır; kapı bu yüzden başlangıçta görünür.
|
||||
ttk.Label(
|
||||
header,
|
||||
text=ROOT_REQUIRED_NOTICE,
|
||||
foreground="#a05000",
|
||||
).pack(anchor="w")
|
||||
|
||||
def _build_mode_bar(self) -> None:
|
||||
bar = ttk.Frame(self.root)
|
||||
|
|
@ -2912,14 +2866,6 @@ class BfGui: # pragma: no cover - pencere gerektirir (statik testler dokunmaz)
|
|||
self.output.write_now("=" * 72)
|
||||
|
||||
def _start_run(self, plan: CommandPlan) -> None:
|
||||
if plan.needs_root and not write_operations_enabled():
|
||||
# The button is disabled for this case, so reaching here means the
|
||||
# gate was bypassed (stale widget state, a future caller). Refusing
|
||||
# in the one place every run goes through keeps the rule true for
|
||||
# the whole surface instead of one control.
|
||||
self.output.write_now("[ENGELLENDİ] " + NON_ROOT_DISABLED_HINT)
|
||||
self.status.configure(text="Yönetici yetkisi gerekli.")
|
||||
return
|
||||
self.running = True
|
||||
self.cancel_event.clear()
|
||||
self.run_button.configure(state="disabled")
|
||||
|
|
@ -3032,34 +2978,6 @@ def print_catalogue(backend, stream=None) -> None:
|
|||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Yetki kapisi
|
||||
# ---------------------------------------------------------------------------
|
||||
def is_root() -> bool:
|
||||
"""True when the process can install, write state and drive Ansible.
|
||||
|
||||
The installer writes to the filesystem, manages services and applies the
|
||||
firewall baseline, so the GUI is expected to run under sudo. Reports read
|
||||
the repository and the inventory and work without it, which is why the
|
||||
console still starts as a normal user and explains the difference instead
|
||||
of refusing to launch.
|
||||
"""
|
||||
geteuid = getattr(os, "geteuid", None)
|
||||
return True if geteuid is None else geteuid() == 0
|
||||
|
||||
|
||||
ROOT_REQUIRED_NOTICE = (
|
||||
"Yönetici yetkisi yok: salt-okunur raporlar çalışır, kurulum ve değişiklik "
|
||||
"gerektiren işlemler kapalıdır. Tam yetki için: sudo bf"
|
||||
)
|
||||
NON_ROOT_DISABLED_HINT = "Bu işlem yönetici yetkisi gerektirir (sudo bf)."
|
||||
|
||||
|
||||
def write_operations_enabled() -> bool:
|
||||
"""Whether operations that change the device may be offered."""
|
||||
return is_root()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Baslatma
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -1,40 +1,37 @@
|
|||
# 05 — Tek-Tık Kurucu (One-Click Installer)
|
||||
|
||||
> Kısa özet: Sahadaki tek giriş noktası **grafik operatör uygulamasıdır**: `sudo bf` → Kurulum sekmesi → "Bu cihazı kur". Bayi no doğrulaması, 18 modül, idempotent yeniden-koşu ve final-check kapısı `blueforce-install.sh`'ın işidir. Paketler git deposunda taşınır; **kurulum internetsizdir**. Terminal yedeği: `sudo bf --tui`.
|
||||
> Kısa özet: Sahada tek komutla cihazı READY yapan `blueforce-install.sh`: bayi no doğrulaması, 18 modül, idempotent yeniden-koşu ve final-check kapısı. Teknisyenin çalıştırdığı tek şeydir.
|
||||
|
||||
- Dosya: `docs/05-ONE-CLICK-INSTALLER.md`
|
||||
- İlgili kararlar: `24-DECISION-LOG.md#K-09` (tek kurucu), `K-11` (update kapalı), `K-12` (kimlik formatı), `K-03` (bf-gui), `K-10` (Docker disiplini), `K-16` (offline)
|
||||
- İlgili dokümanlar: `33-OPERATOR-CONSOLE.md` (arayüz rehberi), `27-OFFLINE-PROVISIONING.md` (paket deposu sözleşmesi)
|
||||
- İlgili kararlar: `24-DECISION-LOG.md#K-09` (tek kurucu), `K-11` (update kapalı), `K-12` (kimlik formatı), `K-03` (bf-gui), `K-10` (Docker disiplini)
|
||||
- Durum: [ ] Taslak
|
||||
|
||||
---
|
||||
|
||||
## 1. Amaç
|
||||
|
||||
Saha teknisyeninin uzmanlık gerektirmeden cihazı standarda getirmesi: tek giriş noktası (`sudo bf`), tek girdi (8 haneli bayi no), net sonuç (`PROVISIONED_OFFLINE` / hata + neden). Yarım kalan veya hatalı kurulumun güvenli tekrarı.
|
||||
|
||||
Teknisyen terminal komutu, bayrak veya dosya yolu ezberlemez: kurulum grafik arayüzdeki düğmeyle başlatılır, komut arayüzde gösterilir ve onay alınmadan çalıştırılmaz.
|
||||
Saha teknisyeninin uzmanlık gerektirmeden cihazı standarda getirmesi: tek komut, tek girdi (bayi no), net sonuç (READY / hata + log yolu). Yarım kalan veya hatalı kurulumun güvenli tekrarı.
|
||||
|
||||
## 2. Kapsam
|
||||
|
||||
- Kapsam içi: grafik uygulama üzerinden kurulum akışı, kurucu betiğin komut yüzeyi, bayi-no doğrulama, 18 modül listesi ve sırası, paket deposu keşfi ve hata durumları, idempotency kuralları, log/çıkış kodları.
|
||||
- Kapsam dışı: modül iç kodları (repo `scripts/install/installer/modules/`), imaj üretim yöntemi (04), filo-side yapılandırma (09), arayüzün tüm ekranları (33).
|
||||
- Kapsam içi: komut arayüzü, bayi-no doğrulama, 18 modül listesi ve sırası, idempotency kuralları, log/bundle çıktısı, çıkış kodları.
|
||||
- Kapsam dışı: modül iç kodları (repo `scripts/install/`), imaj üretim yöntemi (04), filo-side yapılandırma (09).
|
||||
|
||||
## 3. Kararlar
|
||||
|
||||
```text
|
||||
KARAR: Saha kurulumunun tek giriş noktası grafik operatör uygulamasıdır: `sudo bf` → Kurulum sekmesi → "Bu cihazı kur". Kurucu betik (`scripts/install/blueforce-install.sh`) bu düğmenin çağırdığı motordur ve aynı akış terminalden `sudo bf --tui` ile de yürütülebilir. Eski bash menü (`admin/bf-menu`) yedek yoldur, ana yol değildir.
|
||||
GEREKÇE: Tek giriş noktası ve tek düğme teknisyen hatasını en aza indirir; grafik arayüz komutu çalıştırmadan önce gösterir ve onay ister, böylece görünmez komut kalmaz. Bayi no `^[0-9]{8}$` ile doğrulanır; format kapısı yanlış kimliğin 9 sisteme yayılmasını baştan engeller (K-12).
|
||||
ALTERNATİF: Yalnız bash menülü kurulum (`admin/bf-menu`) — grafik arayüz yoksa çalışır ama sahadaki ana yolu oluşturmaz; yedek olarak korundu. Çok scriptli kurulum (ağ.sh, gui.sh, …) — sıra hatası ve atlanan adım riski nedeniyle elendi.
|
||||
RİSK: Tek dosya büyüdükçe bakımı zorlaşır; azaltma: 18 bağımsız modül + ana orkestratör ayrımı. Grafik arayüz `python3-tk` gerektirir; azaltma: paket offline depoda pinlidir ve ekransız/paketsiz ortamda uygulama Türkçe yönlendirme yapıp `--tui` önerir.
|
||||
KARAR: Saha kurulumu tek giriş noktasıdır: `sudo ./blueforce-install.sh --dealer-id <8hane>`; bayi no `^[0-9]{8}$` ile doğrulanır, uymayan girdi kurucuyu başlatmaz.
|
||||
GEREKÇE: Tek komut teknisyen hatasını en aza indirir; format kapısı yanlış kimliğin 9 sisteme yayılmasını baştan engeller (K-12).
|
||||
ALTERNATİF: Çok scriptli kurulum (ağ.sh, gui.sh, …) — sıra hatası ve atlanan adım riski nedeniyle elendi.
|
||||
RİSK: Tek dosya büyüdükçe bakımı zorlaşır; azaltma: 18 bağımsız modül + ana orkestratör ayrımı.
|
||||
MALİYET: Ücretsiz.
|
||||
LİSANS: Yok (şirket içi script + standart kütüphane ile yazılmış Python arayüz).
|
||||
LİSANS: Yok (şirket içi script).
|
||||
```
|
||||
|
||||
```text
|
||||
KARAR: Kurucu 18 modülden oluşur (`01-precheck` … `18-final-check`); her modül idempotenttir — yeniden koşu güvenli ve kaldığı yerden tamamlayıcıdır. Paketler yerel paket deposundan gelir ve depo otomatik bulunur; `--offline` bayrağı zorunlu değildir.
|
||||
GEREKÇE: Saha elektriği/kesintisi yarım kurulum üretir; idempotency olmadan her kesinti temiz-kurulum demektir. Final-check kapısı (modül 18) exit 0 vermeden cihaz kurulu sayılmaz; offline akışta sonuç `PROVISIONED_OFFLINE`, token sonrası `ENROLLED`, yalnız merkezi kanallar doğrulanınca `READY` olur (27/29). Depoyu kuran kişinin hatırlaması gereken bayrak sayısı sıfırdır.
|
||||
ALTERNATİF: Tek seferlik (non-idempotent) script — kesinti durumunda belirsiz ara durum nedeniyle elendi. `--offline` bayrağını zorunlu tutmak — operatör bayrağı unuttuğunda kurulum durur; bayrak geriye uyumluluk için korundu.
|
||||
KARAR: Kurucu 18 modülden oluşur (`01-precheck` … `18-final-check`); her modül idempotenttir — yeniden koşu güvenli ve kaldığı yerden tamamlayıcıdır.
|
||||
GEREKÇE: Saha elektriği/kesintisi yarım kurulum üretir; idempotency olmadan her kesinti temiz-kurulum demektir. Final-check kapısı (modül 18) exit 0 vermeden cihaz kurulu sayılmaz; offline akışta sonuç `PROVISIONED_OFFLINE`, token sonrası `ENROLLED`, yalnız merkezi kanallar doğrulanınca `READY` olur (27/29).
|
||||
ALTERNATİF: Tek seferlik (non-idempotent) script — kesinti durumunda belirsiz ara durum nedeniyle elendi.
|
||||
RİSK: Modülün idempotent yazılmaması (çift kayıt, çift key); azaltma: §10'daki çift-koşu testi her modül için zorunlu.
|
||||
MALİYET: Ücretsiz.
|
||||
LİSANS: Yok.
|
||||
|
|
@ -42,203 +39,115 @@ LİSANS: Yok.
|
|||
|
||||
## 4. Neden Bu Karar?
|
||||
|
||||
700 cihaz × teknisyen başına değişen beceri = kurulumun "tek düğme + tek soru" olması şarttır. Grafik arayüz bu düğmeyi verir; 18 modül ise her kararın (update-kapalı, Docker-disiplini, GUI-anahtarı, kimlik, servisler) ayrı denetlenebilir adımıdır. Modül numarası log satırında görünür, arıza hangi adımda kaldıysa oradan devam edilir; arayüz aynı durumu "Kurulum modül durumu" işlemiyle salt-okunur gösterir.
|
||||
700 cihaz × teknisyen başına değişen beceri = kurulumun "tek komut + tek soru" olması şarttır. 18 modül, her kararın (update-kapalı, Docker-disiplini, GUI-anahtarı, kimlik, servisler) ayrı denetlenebilir adımdır; modül numarası log satırında görünür, arıza hangi adımda kaldıysa oradan devam edilir.
|
||||
|
||||
## 5. Alternatifler
|
||||
|
||||
| Alternatif | Artı | Eksi | Sonuç |
|
||||
|---|---|---|---|
|
||||
| Grafik arayüz + tek kurucu betik | Tek giriş, komut ezberi yok, onay görünür | Grafik katman gerekir (`python3-tk`, ekran) | **Seçildi** |
|
||||
| Yalnız bash menülü kurulum (`admin/bf-menu`) | Grafik katman gerekmez | Ana yol olarak terminal bilgisi ister; ekran yok | Yedek yol |
|
||||
| Çok scriptli kurulum | Küçük dosyalar | Sıra/atlama hatası | Elendi |
|
||||
| Non-idempotent tek script | Daha basit kod | Kesintide temiz-kurulum zorunluluğu | Elendi |
|
||||
| İnteraktif sihirbaz (çok sorulu) | Esnek | Teknisyen hatası, otomasyona kapalı | Elendi |
|
||||
|
||||
## 6. Avantajlar
|
||||
|
||||
- Tek giriş noktası (`sudo bf`) = eğitim maliyeti minimum, runbook tek sayfa.
|
||||
- Tek komut = eğitim maliyeti minimum, runbook tek sayfa.
|
||||
- Idempotency = kesinti korkusu yok, "bir daha koş" her sorunun ilk cevabı.
|
||||
- Final-check = kurulum sonucu ölçülebilir, dalga kapılarına bağlanır.
|
||||
- İnternetsiz çalışır: paketler repoda gelir, kuran kişi hiçbir şey indirmez.
|
||||
- Final-check = READY iddiası ölçülebilir, dalga kapılarına bağlanır.
|
||||
|
||||
## 7. Dezavantajlar
|
||||
|
||||
- 18 modülün her biri için idempotency testi yazma maliyeti.
|
||||
- Tek giriş noktası, modül-atlama (debug) ihtiyacında `--from/--only/--resume` bayraklarını zorunlu kılar.
|
||||
- Grafik arayüz `python3-tk` paketine ve bir grafik oturuma bağlıdır; bu ikisi yoksa operatör terminal konsoluna (`sudo bf --tui`) düşer.
|
||||
- Tek giriş noktası, modül-atlama (debug) ihtiyacında `--from/--only` bayraklarını zorunlu kılar.
|
||||
|
||||
## 8. Riskler
|
||||
|
||||
| Risk | Olasılık | Etki | Azaltma |
|
||||
|---|---|---|---|
|
||||
| Modül idempotent değil (çift kayıt) | Orta | Orta | Çift-koşu testi (§10) + code review kuralı |
|
||||
| Teknisyen yanlış no girer | Orta | Orta | Format kapısı (`^[0-9]{8}$`) + onay ekranı (`BF-12010193, onaylıyor musunuz?`) |
|
||||
| Kurucu yarıda kesilir, cihaz ara durumda sahaya alınır | Düşük | Yüksek | Final-check exit 0 olmadan kurulum tamamlanmaz; arayüzdeki "Kurulum modül durumu" ve `bf-status` bunu gösterir |
|
||||
| Grafik arayüz açılmaz (başsız oturum) | Orta | Düşük | Uygulama Türkçe hata + `sudo bf --tui` önerir (19 §T-10) |
|
||||
| `python3-tk` eksik kalır | Düşük | Orta | Paket offline depoda pinli; `18-final-check` tkinter'ı denetler ve eksikse WARN yazar |
|
||||
| Teknisyen yanlış no girer | Orta | Orta | Format kapısı + onay ekranı (`BF-xxxx, onaylıyor musunuz?`) |
|
||||
| Kurucu yarıda kesilir, cihaz ara durumda sahaya alınır | Düşük | Yüksek | Final-check exit 0 olmadan READY yok; `bf-status` bunu gösterir |
|
||||
|
||||
## 9. Uygulama Planı
|
||||
|
||||
### 1. Giriş noktası — grafik operatör uygulaması (ana yol)
|
||||
1. Komut arayüzü:
|
||||
|
||||
```bash
|
||||
sudo bf # grafik arayüz (bfos paketi, bfos/ui_gui.py, Tkinter)
|
||||
```
|
||||
|
||||
Akış:
|
||||
|
||||
1. Pencere açılır: başlık **Blueforce Field OS — Yönetim**.
|
||||
2. Basit modda üç düğme vardır: `Kur`, `Durum`, `Çıkış`. Üstteki **`Detaylı mod`** ile 5 sekme açılır: `Kurulum`, `Cihaz işlemleri`, `Merkez hazırlığı`, `Araçlar`, `Cihaz bilgisi`.
|
||||
3. Üst çubuktaki **Hedef > Bayi no (8 hane)** alanına numara yazılır (örn. `12010193`); format geçersizse arayüz uyarır ve komut üretilmez.
|
||||
4. `Kurulum` sekmesinde **`Bu cihazı kur`** (veya hiçbir şey yazmayan ön kontrol **`Kurulum ön kontrolü (--check)`**) seçilir.
|
||||
5. Arayüz komutu **önce ekranda gösterir**, sonra onay ister; onaylanmadan çalıştırılmaz. Yıkıcı işlemler ikinci kez sorar; production kapsamı ayrı onay ister.
|
||||
6. Kurulum çıktısı ekranda akar; bitince sonuç ve çıkış kodu görünür.
|
||||
|
||||
`Bu cihazı kur` işleminin iki opsiyonel seçeneği vardır: `Yerel çevrimdışı depodan kur (--offline)` ve `Zaten OK olan modülleri atla (--resume)`. **`--offline` işaretlenmese de varsayılan kaynak yerel depodur**; bayrak yalnız niyeti sabitler.
|
||||
|
||||
### 2. Yedek yol — terminal konsolu
|
||||
|
||||
```bash
|
||||
sudo bf --tui # aynı uygulamanın terminal arayüzü (grafik ekran yoksa / tkinter yoksa)
|
||||
```
|
||||
|
||||
- `DISPLAY` ve `WAYLAND_DISPLAY` tanımlı değilse (SSH, başsız kurulum) uygulama Türkçe açıklama yazar ve **çıkış kodu 3** ile `sudo bf --tui` önerir.
|
||||
- `python3-tk` kurulu değilse (`tkinter` import edilemiyor) aynı şekilde Türkçe hata + `python3-tk` kurulum ipucu verir ve **çıkış kodu 3** ile terminal konsolunu önerir.
|
||||
- Eski bash menü `sudo admin/bf-menu` **yalnız yedek yoldur**; dokümanlarda ve iş akışında ana yol olarak kullanılmaz.
|
||||
|
||||
### 3. Yetki
|
||||
|
||||
- `sudo bf` = tam yetki (kurulum, servis, firewall, Ansible).
|
||||
- Root değilse uygulama başlangıçta uyarır ve yalnız **salt-okunur raporları** çalıştırır: "Yönetici yetkisi yok: salt-okunur raporlar çalışır, kurulum ve değişiklik gerektiren işlemler kapalıdır. Tam yetki için: sudo bf". Yazma işlemleri hem arayüzde kapalıdır hem de çalıştırma katmanında reddedilir (onaylansa bile komut çalışmaz).
|
||||
|
||||
### 4. Bayi-no doğrulama
|
||||
|
||||
`^[0-9]{8}$`; uymazsa arayüz geçersiz numarayı reddeder ve kurucu komut üretilmez (doğrudan CLI kullanımında exit 2 + kullanım mesajı). Geçerliyse onay ekranında `BF-12010193` + hostname `bf-12010193` gösterilir.
|
||||
|
||||
### 5. 18 modül (sıra sözleşmedir, yeri `scripts/install/installer/modules/`)
|
||||
|
||||
| # | Modül | İşlev |
|
||||
|---|---|---|
|
||||
| 01 | `01-precheck` | Root, Ubuntu sürümü, RAM/disk ön kontrolü; ağ yalnız bilgi (kapı değil) |
|
||||
| 02 | `02-system` | Temel APT kaynakları, `unattended-upgrades` kapatma, saat dilimi (K-11) |
|
||||
| 03 | `03-user` | `blueforce` bakım kullanıcısı, kısıtlı sudoers, zorunlu yönetici anahtarı (K-13) |
|
||||
| 04 | `04-hostname` | Doğrulanmış bayi no'dan hostname `bf-<no>` (K-12) |
|
||||
| 05 | `05-network` | Ağ raporu: yerel bağlantı, rota/DNS (DNS zorunlu tutulmaz — offline kurulum) |
|
||||
| 06 | `06-wireguard` | Cihaz anahtar çifti; `wg0.conf` enrollment'ın işidir (K-05/K-17) |
|
||||
| 07 | `07-ssh` | Yönetici anahtarı doğrulandıktan **sonra** sshd sertleştirme |
|
||||
| 08 | `08-rdp` | xRDP + GNOME oturumu, terminale boot varsayılanı, multi-user (K-03/K-22) |
|
||||
| 09 | `09-rustdesk` | Yalnız pinli/sağlanan paketten RustDesk istemci (K-04) |
|
||||
| 10 | `10-docker` | Docker CE + rotasyonlu `daemon.json` + enable (K-10) |
|
||||
| 11 | `11-meg` | MEG yer tutucusu: vendor `.deb` varsa kurar, yoksa SKIP + kabul listesi |
|
||||
| 12 | `12-monitoring` | Node Exporter + textfile collector dizini (K-07) |
|
||||
| 13 | `13-firewall` | UFW deny-in tabanı + Docker yayın-portu politikasının kalıcılığı (K-05/K-10) |
|
||||
| 14 | `14-update-policy` | APT hold'ları + otomatik update zamanlayıcılarını kapatma (K-11) |
|
||||
| 15 | `15-logrotate` | journald tavanları + uygulama logrotate politikası (K-14) |
|
||||
| 16 | `16-gui` | GNOME minimal + bakım araçları; terminale boot varsayılanı (K-03) |
|
||||
| 17 | `17-healthcheck` | Teşhis ve enrollment komutlarını kurar; enrollment'ı çalıştırmaz |
|
||||
| 18 | `18-final-check` | Son yaşam döngüsü kapısı: offline yerelde tamamlanır, `READY` merkez kanıtı ister; tkinter denetimi (yoksa WARN) |
|
||||
|
||||
Modül çıkış kodları: `0` OK, `3` SKIP (opsiyonel adım, yapılacak bir şey yok), diğer ≠ 0 FAIL.
|
||||
|
||||
### 6. Paket deposu — otomatik keşif, iki hata durumu, sıfır indirme
|
||||
|
||||
Installer paket deposunu **kendi bulur**; `--offline` bayrağı **gerekmez** (geriye uyumluluk için kabul edilir, yalnız yerel depoyu zorlar). Arama sırası (ilk eksiksiz aday kazanır):
|
||||
|
||||
1. `BF_OFFLINE_REPO` ortam değişkeni (operatör/repo sorumlusu override'ı),
|
||||
2. `<repo>/provisioning/offline-repo/built` (git deposuyla gelen paket seti),
|
||||
3. `/opt/blueforce/offline-repo` (cihaza kurulmuş paket deposu).
|
||||
|
||||
Depo bulunduğunda ekrana Türkçe duyuru yazılır: `Yerel paket deposu bulundu: <N> paket, <boyut>` + `Depo`, `Kaynak`, `Kip` satırları. İki farklı başarısızlık vardır ve **ikisinde de paket modüllerinden önce durulur, sistemde hiçbir değişiklik yapılmaz**:
|
||||
|
||||
| Durum | Ekran | Sonuç |
|
||||
|---|---|---|
|
||||
| Depo hiçbir yerde yok | `HATA: Yerel paket deposu yok. Repo sorumlusuna başvurun: provisioning/offline-repo/README.md` + aranan yollar + `ÇIKIŞ NEDENİ: yerel paket deposu bulunamadı.` | exit 1 |
|
||||
| Depo bulundu ama bozuk/eksik | `OFFLINE BLOCKED: <sebep>` + Türkçe çıkış nedeni (ör. checksum uyuşmazlığı, eksik `Packages`/`packages.lock.tsv`, eksik pin) | exit 1 |
|
||||
|
||||
Uzak APT kaynağı, `curl`, `wget`, anahtar indirme veya `apt download` çağrılmaz. Yalnız geliştirme/test için `--online` vardır ve üretim cihazlarında kullanılmaz (DİKKAT uyarısı yazar).
|
||||
|
||||
### 7. Kurucu betiğin komut yüzeyi (yedek/otomasyon)
|
||||
|
||||
```bash
|
||||
sudo ./scripts/install/blueforce-install.sh --dealer-id 12010193 [--from 07] [--only 18-final-check] [--resume] [--check] [--yes]
|
||||
sudo ./blueforce-install.sh --dealer-id 12010193 [--from 07] [--only 18-final-check] [--check]
|
||||
# --check: değişiklik yapmadan denetim (final-check + modül durumları)
|
||||
# --from : belirtilen modülden devam et | --only: tek modül koş | --resume: OK modülleri atla
|
||||
# --yes : onay sormadan başla (otomasyon; GUI bu bayrağı kullanmaz)
|
||||
# --offline: yerel depoyu zorla (varsayılan zaten yerel) | --online: yalnız geliştirme/test
|
||||
# --from: belirtilen modülden devam et | --only: tek modül koş
|
||||
```
|
||||
|
||||
### 8. Idempotency kuralları (her modül için zorunlu)
|
||||
2. Bayi-no doğrulama: `^[0-9]{8}$`; uymazsa exit 2 + kullanım mesajı. Geçerse onay ekranı (`BF-12010193` + hostname `bf-12010193` gösterilir).
|
||||
3. 18 modül (sıra sözleşmedir, yeri `scripts/install/`):
|
||||
|
||||
| # | Modül | İşlev (dayandığı karar) |
|
||||
|---|---|---|
|
||||
| 01 | `01-precheck` | OS sürümü (26.04.1+), disk/RAM minimumu, root yetkisi, internet kontrolü |
|
||||
| 02 | `02-dealer-id` | No doğrulama + hostname `bf-<no>` atama (K-12) |
|
||||
| 03 | `03-base-packages` | Temel paketler + `unattended-upgrades` kapatma (K-11) |
|
||||
| 04 | `04-gnome` | GNOME kurulumu (K-02) |
|
||||
| 05 | `05-xrdp` | xRDP + sesman + `bf-gui-on/off` yazımı (K-03) |
|
||||
| 06 | `06-ssh-hardening` | `blueforce` kullanıcısı, key-auth, root/password kapalı (K-13) |
|
||||
| 07 | `07-wireguard` | Spoke config, peer `bf-<no>`, keepalive 25, `wg-quick@wg0` enable (K-05) |
|
||||
| 08 | `08-docker` | Docker CE + `unless-stopped` + log rotasyonu + localhost-bind (K-10) |
|
||||
| 09 | `09-meg` | MEG konteyneri (sabit tag, `latest` yok) (K-10) |
|
||||
| 10 | `10-rustdesk` | RustDesk istemci + VDS adresi + `BF-<no>` etiketi (K-04) |
|
||||
| 11 | `11-meshcentral` | MeshCentral agent + `BF-<no>` adı (K-04) |
|
||||
| 12 | `12-monitoring` | Node Exporter + textfile + Uptime Push (K-07) |
|
||||
| 13 | `13-firewall` | UFW profili (SSH/RDP yalnızca WG) (K-05) |
|
||||
| 14 | `14-inventory` | `bf-hardware-inventory.sh` koşusu, JSON+MD üretimi (02) |
|
||||
| 15 | `15-logging` | journald + Docker rotasyon + `bf-status/bf-diagnostics` (K-14) |
|
||||
| 16 | `16-boot` | multi-user default + BIOS notu + servis enable denetimi (K-03) |
|
||||
| 17 | `17-ansible-bootstrap` | Bootstrap SSH key + ilk pull/Ansible kaydı (K-06/K-13) |
|
||||
| 18 | `18-final-check` | Tüm kapılar: kimlik, servisler, update-kapalı, Docker politikası, READY damgası |
|
||||
|
||||
4. Idempotency kuralları (her modül için zorunlu):
|
||||
- Varlık kontrolü önce (`id blueforce`, `dpkg -l`, `systemctl is-enabled`): varsa atla, yoksa kur.
|
||||
- Dosya yazımları atomik (tmp + rename) ve tekrarlanabilir (aynı girdi → aynı çıktı).
|
||||
- Anahtar/secret üretimi bir kez; `--force` olmadan yeniden üretilmez.
|
||||
- Her modül `/var/log/blueforce-install.log` dosyasına modül no + OK/SKIP/FAIL satırı yazar.
|
||||
|
||||
### 9. Çıkış kodları ve sonuç durumu
|
||||
|
||||
Kurucu betik: `0` başarı (offline akışta `PROVISIONED_OFFLINE`), `1` engellendi veya modül hatası (no logda), `2` argüman/format hatası. Grafik/terminal arayüz: `3` grafik katman yok (ekran veya `python3-tk`), `2` kullanım hatası (`--tui` + `--gui` birlikte verilemez), `0` normal kapanış.
|
||||
|
||||
`READY` bir kurucu çıkış kodu değildir: offline akış `PROVISIONED_OFFLINE` yazar, `READY` yalnız merkezi kanallar doğrulandığında (29/30) yazılır.
|
||||
- Anahtar/secret üretimi bir kez (`/var/lib/blueforce/.modül-done` damgası); `--force` olmadan yeniden üretilmez.
|
||||
- Her modül `/var/log/blueforce-install.log` dosyasına `MODÜL-NO + OK/SKIP/FAIL` satırı yazar.
|
||||
5. Çıkış kodları: `0` READY, `1` modül hatası (no logda), `2` argüman/format hatası.
|
||||
|
||||
## 10. Test Planı
|
||||
|
||||
| Test | Beklenen sonuç | Ortam |
|
||||
|---|---|---|
|
||||
| Geçersiz no (7/9 hane, harf, boş) | Arayüz reddeder / CLI exit 2, kurulum başlamaz | LAB(2) |
|
||||
| `sudo bf` ile kurulum (grafik) | Komut önce gösterilir, onay ister, kurulum `PROVISIONED_OFFLINE` ile biter | LAB(2) masaüstü oturumu |
|
||||
| `DISPLAY` yokken `sudo bf` | Türkçe yönlendirme + `sudo bf --tui` önerisi, exit 3, sistem değişmez | LAB(2) SSH |
|
||||
| `python3-tk` yokken `sudo bf` | Türkçe "tkinter bulunamadı" + paket ipucu, exit 3 | LAB(2) minimal imaj |
|
||||
| Geçersiz no (7/9 hane, harf, boş) | exit 2, kurulum başlamaz | LAB(2) |
|
||||
| Her modülün çift-koşusu | İkinci koşu exit 0, durum değişmez (diff boş) | LAB(2) |
|
||||
| Elektrik-kesintisi simülasyonu (modül 09 ortasında kill) | `--from 09` veya arayüzdeki `--resume` ile tamamlanır, final exit 0 | LAB(2) |
|
||||
| `18-final-check` tüm kapıları | Eksik adımda FAIL + modül nosu, başarı damgası yok | LAB(2) |
|
||||
| `--check` kuru koşusu (GUI ön kontrol / CLI) | Değişiklik yapmaz, rapor üretir | P1(5) |
|
||||
| Depo yokken kurulum denemesi | Türkçe hata + aranan yollar + çıkış nedeni, exit 1, sistem değişmez | LAB(2) |
|
||||
| Depo bozukken kurulum denemesi | `OFFLINE BLOCKED: <sebep>` + Türkçe çıkış nedeni, exit 1 | LAB(2) |
|
||||
| Elektrik-kesintisi simülasyonu (modül 09 ortasında kill) | `--from 09` ile tamamlanır, final exit 0 | LAB(2) |
|
||||
| `18-final-check` tüm kapıları | Eksik adımda FAIL + modül nosu, READY yok | LAB(2) |
|
||||
| `--check` kuru koşusu | Değişiklik yapmaz, rapor üretir | P1(5) |
|
||||
|
||||
## 11. Rollback
|
||||
|
||||
1. Modül hatası: arayüzdeki "Kurulum modül durumu"/log ile modül nosu bulunur; `--from <no>` veya arayüzdeki `Başarısız kuruluma devam et (--resume)` ile sürdürülür.
|
||||
2. Yanlış no: doğru no ile tam yeniden koşu (idempotent, hostname modülü üzerine yazar).
|
||||
1. Modül hatası: logdaki modül nosundan `--from <no>` ile devam edilir.
|
||||
2. Yanlış no: doğru no ile tam yeniden koşu (idempotent, kimlik modülü üzerine yazar).
|
||||
3. Düzelmeyen cihaz: 17-RECOVERY LEVEL 9 (temiz imaj + kurucu).
|
||||
4. Paket deposu bozuksa sahada onarılmaz: repo sorumlusu depoyu yeniden üretip commit eder, güncel git tarafı çekilir ve komut tekrarlanır (27 §11).
|
||||
|
||||
## 12. Kontrol Listesi
|
||||
|
||||
- [ ] 18 modül dosyası `scripts/install/installer/modules/` altında numaralı ve çalışır durumda.
|
||||
- [ ] Grafik arayüzde `Kurulum` sekmesi ve `Bu cihazı kur` işlemi bayi-no kapısına bağlı.
|
||||
- [ ] Uygulama ekransız ortamda ve tkinter yokken Türkçe yönlendirme + `--tui` önerisi verip exit 3 ile çıkıyor.
|
||||
- [ ] Her modülde varlık-kontrolü + log satırı var.
|
||||
- [ ] 18 modül dosyası `scripts/install/` altında numaralı ve çalışır durumda.
|
||||
- [ ] Her modülde varlık-kontrolü + damga + log satırı var.
|
||||
- [ ] Format regex'i 02 ile aynı (`^[0-9]{8}$`).
|
||||
- [ ] `18-final-check` K-10/K-11 kapılarını ve tkinter denetimini içeriyor.
|
||||
- [ ] Depo keşif sırası ve iki hata durumu (yok / bozuk) ekranda Türkçe ve fail-closed.
|
||||
- [ ] `--check/--from/--only/--resume` bayrakları çalışıyor; `--offline` zorunlu değil.
|
||||
- [ ] `18-final-check` K-10/K-11 kapılarını denetliyor (unless-stopped, latest yok, update kapalı).
|
||||
- [ ] `--check/--from/--only` bayrakları çalışıyor.
|
||||
|
||||
## 13. Açık Sorular
|
||||
|
||||
- [ ] Paket setinin sahaya taşınması: git clone (Git LFS) mı, repo sorumlusunun hazırladığı `/opt/blueforce/offline-repo` kopyası mı birincil? (sahibi: Faz 3, 04/27 yazarları ile ortak)
|
||||
- [ ] Kurucu USB'de mi, merkezden `curl` ile mi alınacak (saha interneti varsayımı) (sahibi: Faz 3, 04 yazarı ile ortak).
|
||||
- [ ] MEG sabit tag'inin kim tarafından, hangi onay ile güncelleneceği (sahibi: 10-UPDATE / 12-DOCKER yazarları).
|
||||
- [ ] Arayüzün grafik ekran gerektirmeyen cihazlarda varsayılan modu (`--tui` mi, grafik mi) — saha ölçümü ile karar (sahibi: 33 + saha operasyonu).
|
||||
|
||||
---
|
||||
|
||||
## Ek: Kurulum Akışı (grafik arayüz)
|
||||
## Ek: Kurucu Akış
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
CMD["sudo bf<br/>(grafik operatör uygulaması)"] --> EKRAN{"Grafik ekran +<br/>python3-tk var mı?"}
|
||||
EKRAN -->|Hayır| TUI["Türkçe yönlendirme + exit 3<br/>sudo bf --tui"]
|
||||
EKRAN -->|Evet| HEDEF["Hedef: Bayi no (8 hane)"]
|
||||
HEDEF --> FMT{"^[0-9]{8}$ ?"}
|
||||
FMT -->|Hayır| UYARI["Arayüz uyarır<br/>komut üretilmez"]
|
||||
FMT -->|Evet| KUR["Kurulum sekmesi<br/>'Bu cihazı kur'"]
|
||||
KUR --> ONAY["Komut gösterilir + onay<br/>(yıkıcı: ikinci onay)"]
|
||||
ONAY --> DEPO{"Yerel paket deposu aranır<br/>BF_OFFLINE_REPO → built → /opt/blueforce/offline-repo"}
|
||||
DEPO -->|"hiçbiri yok"| YOK["Türkçe hata + aranan yollar<br/>ÇIKIŞ NEDENİ: bulunamadı · exit 1"]
|
||||
DEPO -->|"bozuk/eksik"| BOZ["OFFLINE BLOCKED: sebep<br/>exit 1 · sistem değişmez"]
|
||||
DEPO -->|"eksiksiz"| M01["01-precheck … 17-healthcheck<br/>(idempotent modüller)"]
|
||||
CMD["sudo ./blueforce-install.sh<br/>--dealer-id <8hane>"] --> FMT{"^[0-9]8$ ?"}
|
||||
FMT -->|Hayır| EXIT2["exit 2<br/>kullanım mesajı"]
|
||||
FMT -->|Evet| M01["01-precheck … 17-bootstrap<br/>(idempotent modüller)"]
|
||||
M01 --> M18["18-final-check"]
|
||||
M18 -->|Hepsi OK| OFFLINE["PROVISIONED_OFFLINE"]
|
||||
M18 -->|FAIL| LOG["modül nosu + log yolu<br/>--from / --resume ile devam"]
|
||||
OFFLINE --> ENR["Token → ENROLLED"]
|
||||
ENR --> READY["Merkez kanalları doğrulandı → READY"]
|
||||
M18 -->|Tümü OK| READY["READY damgası<br/>bf-status yeşil"]
|
||||
M18 -->|FAIL| LOG["modül nosu + log yolu<br/>--from ile devam"]
|
||||
```
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ Tekrar eden arızalarda teşhisi hızlandırmak: belirtiyi bulan teknisyen/admin
|
|||
|
||||
## 2. Kapsam
|
||||
|
||||
- Kapsam içi: boot, ağ/VPN, SSH, RDP/GUI, RustDesk, MeshCentral, Docker/MEG, disk, monitoring ve operatör arayüzü (grafik/terminal konsol, paket deposu keşfi) belirti tabloları.
|
||||
- Kapsam dışı: seviye kararları (17), adım-adım kurulum (20), merkez onay akışı (21), arayüzün tüm ekranları (33).
|
||||
- Kapsam içi: boot, ağ/VPN, SSH, RDP/GUI, RustDesk, MeshCentral, Docker/MEG, disk, monitoring belirti tabloları.
|
||||
- Kapsam dışı: seviye kararları (17), adım-adım kurulum (20), merkez onay akışı (21).
|
||||
|
||||
## 3. Kararlar
|
||||
|
||||
|
|
@ -69,14 +69,6 @@ docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.RestartPolicy}}'
|
|||
df -h / /var/lib/docker | cat
|
||||
```
|
||||
|
||||
Aynı raporlar operatör arayüzünden de okunur (komut ezberi gerekmez):
|
||||
|
||||
```text
|
||||
Arayüzden: sudo bf → `Durum` düğmesi (Durum özeti) ya da Detaylı mod → Cihaz bilgisi sekmesi
|
||||
(kimlik, ağ/WireGuard, kaynaklar, servisler, son journal hataları — hepsi salt-okunur)
|
||||
Komutla (yedek): sudo bf --tui → Cihaz bilgisi menüsü
|
||||
```
|
||||
|
||||
### T-1 — Cihaz açılmıyor / ekranda hiçbir şey yok
|
||||
|
||||
| # | Neden (olasılık sırası) | Tanı | Çözüm |
|
||||
|
|
@ -155,29 +147,6 @@ Yükseltme: WG kalkmıyorsa RustDesk/MeshCentral ile devam (17-L4); onlar de yok
|
|||
| 2 | Uptime Push gelmiyor | Kuma "last seen" | Cihaz interneti + push job'ı (T-3'e dön) |
|
||||
| 3 | Etiket yanlış (`BF-<no>`) | Prometheus target etiketleri | Envanterle eşitle (02) |
|
||||
|
||||
### T-10 — Grafik operatör arayüzü açılmıyor (`sudo bf` pencere açmıyor / hemen kapanıyor)
|
||||
|
||||
| # | Neden (olasılık sırası) | Tanı | Çözüm |
|
||||
|---|---|---|---|
|
||||
| 1 | Ekran yok (SSH/başsız oturum) | Ekranda "Grafik ekran bulunamadı (DISPLAY ve WAYLAND_DISPLAY tanımlı değil)" + yönlendirme; çıkış kodu `3` | `sudo bf --tui` ile aynı işlemleri terminal konsolunda yürüt; yerel ekranda pencereli kullanmak için oturum açık bir makinede `sudo bf` |
|
||||
| 2 | `python3-tk` kurulu değil (minimal imaj) | "tkinter bulunamadı; masaüstü arayüzü başlatılamıyor" + paket ipucu; çıkış kodu `3` | Çevrimdışı sahada paket kurulmaz: paket offline depoda pinlidir (`manifests/base-packages.txt`) ve normal kurulumla gelir. Eksikse `sudo bf --tui` ile devam et ve merkeze bildir; kurulum sonu kapısı (`18-final-check`) bu durumda **WARN** yazar ve kurulumu düşürmez |
|
||||
| 3 | `DISPLAY` var ama X/Wayland erişilemiyor (ssh -X yok, oturum kilitli) | "Pencere açılamadı; grafik oturumuna erişilemiyor" + teknik ayrıntı; çıkış kodu `3` | `sudo bf --tui`; yerel oturumda çalıştırıyorsan kilitli ekranı aç veya `ssh -X` yerine yerel konsolu kullan |
|
||||
| 4 | Uygulama açıldı ama yazma işlemleri kapalı | Arayüzde "Yönetici yetkisi yok: salt-okunur raporlar çalışır, kurulum ve değişiklik gerektiren işlemler kapalıdır. Tam yetki için: sudo bf" | Komutu `sudo` ile çalıştır; aynı işlem root olmadan çalıştırma katmanında da reddedilir |
|
||||
|
||||
Yükseltme: pencere hiç açılmıyorsa ve `sudo bf --tui` de çalışmıyorsa (Python 3.8+ yok veya `bfos` paketi bulunamıyor) merkeze telefon aç; yedek bash menü `sudo admin/bf-menu` ana yol değildir, yalnız acil yedektir.
|
||||
|
||||
### T-11 — "Yerel paket deposu bulunamadı" (kurulum paket adımlarına geçmiyor)
|
||||
|
||||
| # | Neden (olasılık sırası) | Tanı | Çözüm |
|
||||
|---|---|---|---|
|
||||
| 1 | Depo cihazda hiç yok | Ekranda `HATA: Yerel paket deposu yok. Repo sorumlusuna başvurun: provisioning/offline-repo/README.md` + **aranan yollar** + `ÇIKIŞ NEDENİ: yerel paket deposu bulunamadı.`; çıkış kodu `1`, sistem değişmez | Paket setini git ile tam olarak getir (paketler Git LFS ile gelir) ya da repo sorumlusunun bıraktığı kopyayı `/opt/blueforce/offline-repo` altına koy; kurulumu tekrar çalıştır |
|
||||
| 2 | `packages/` dolu ama indeks (`built/`) yok | Aynı "depo yok" hatası: aday eksiksiz sayılmaz | Kurucu `Packages`, `Packages.gz`, `packages.lock.tsv`, `SHA256SUMS` dosyalarının **hepsini** arar; yalnız `.deb` havuzu yetmez. Repo sorumlusu `build-index.sh` ile `built/` dizinini üretip commit eder |
|
||||
| 3 | Depo bulundu ama bozuk/eksik | `OFFLINE BLOCKED: <sebep>` + Türkçe çıkış nedeni (ör. checksum doğrulaması başarısız, kilit biçimi bozuk, pinlenen paket depoda yok); çıkış kodu `1` | Sahada onarılmaz: repo sorumlusu seti `add-packages.sh` + `build-index.sh` ile yeniden üretir, güncel git tarafı çekilir ve komut tekrarlanır. Cihazda hiçbir değişiklik yapılmadı |
|
||||
| 4 | `BF_OFFLINE_REPO` yanlış | `OFFLINE BLOCKED: BF_OFFLINE_REPO mutlak bir yerel dizin olmalıdır.` | Değişkeni kaldır (varsayılan arama sırası kullanılır) veya geçerli bir mutlak dizin ver |
|
||||
| 5 | "--offline bayrağını vermedim" kuşkusu | — | Bayrak **zorunlu değil**: kurucu depoyu her durumda otomatik arar (sıra: `BF_OFFLINE_REPO` → `<repo>/provisioning/offline-repo/built` → `/opt/blueforce/offline-repo`) |
|
||||
|
||||
Yükseltme: paket seti sahada üretilmez/onarılmaz. İki denemede de aynı hata varsa cihazda hata ayıklamayı bırak, repo sorumlusuna başvur; kurulum paket adımlarına geçmediği için cihaz yarım durumda **kalmaz** (fail-closed).
|
||||
|
||||
## 10. Test Planı
|
||||
|
||||
| Test | Beklenen sonuç | Ortam |
|
||||
|
|
@ -185,9 +154,6 @@ Yükseltme: paket seti sahada üretilmez/onarılmaz. İki denemede de aynı hata
|
|||
| Her T girdisindeki ilk tanı komutu LAB'da çalışır | Komut + örnek çıktı bu dosyada | LAB(2) |
|
||||
| WG-kill → T-3 → L4 onarım tatbikatı | < hedef sürede tünel döner | P1(5) |
|
||||
| Disk-doldur simülasyonu → T-8 | Alarm + temizlik çalışır | LAB(2) |
|
||||
| `DISPLAY` yok + `python3-tk` yok senaryoları → T-10 | Her iki durumda Türkçe yönlendirme, çıkış kodu 3, `--tui` önerisi | LAB(2) |
|
||||
| Depo dizini kaldırılmış cihazda kurulum → T-11 | Türkçe hata + aranan yollar + çıkış nedeni, exit 1, sistem değişmez | LAB(2) |
|
||||
| Yalnız `packages/`, indeks yok → T-11/2 | Kurulum "depo yok" diyerek durur (fail-closed) | LAB(2) |
|
||||
|
||||
## 11. Rollback
|
||||
|
||||
|
|
@ -199,15 +165,12 @@ Yanlış çözüm uygulandıysa 17-L3 (son değişikliği geri alma) işletilir;
|
|||
- [ ] Komutların tamamı LAB 26.04.1 imajında denendi.
|
||||
- [ ] Hiçbir girdide secret/şifre yazılmıyor.
|
||||
- [ ] MEG'e özgü satırlar 13 ile çapraz linkli.
|
||||
- [ ] T-10/T-11 çıkış kodları (3 / 1) ve hata metinleri gerçek çıktıyla doğrulandı.
|
||||
- [ ] Arayüz yolu belirtilen her girdide "Arayüzden" + "Komutla (yedek)" satırı var.
|
||||
|
||||
## 13. Açık Sorular
|
||||
|
||||
- [ ] Kesin `bf-gui-*` birim adları + GNOME oturum satırı — LAB çıktısı (sahibi: Faz 3).
|
||||
- [ ] MEG log hacmi ölçümü → T-8 eşikleri (sahibi: 12-DOCKER yazarı).
|
||||
- [ ] Turkcell CGNAT tanı notları — P1 verisi (sahibi: 08-WIREGUARD yazarı).
|
||||
- [ ] `python3-tk` dışındaki grafik bağımlılıklarının da offline pinde gerekli olup olmadığı — LAB doğrulaması (sahibi: 27 + 33 yazarları).
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -215,10 +178,7 @@ Yanlış çözüm uygulandıysa 17-L3 (son değişikliği geri alma) işletilir;
|
|||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
SORUN["Arıza bildirimi<br/>bf-status + systemctl --failed"] --> ARAC{"Sorun cihaz mı,<br/>operatör arayüzü mü?"}
|
||||
ARAC -->|"Arayüz açılmıyor"| T10["T-10: DISPLAY / tkinter → sudo bf --tui"]
|
||||
ARAC -->|"Kurulum paket adımına geçmiyor"| T11["T-11: yerel paket deposu"]
|
||||
ARAC -->|Cihaz| ACILIR{"Cihaz açılıyor mu?"}
|
||||
SORUN["Arıza bildirimi<br/>bf-status + systemctl --failed"] --> ACILIR{"Cihaz açılıyor mu?"}
|
||||
ACILIR -->|Hayır| T1["T-1: güç / BIOS / disk"]
|
||||
ACILIR -->|Evet| BOOTOK{"Servisler kalkıyor mu?"}
|
||||
BOOTOK -->|Hayır| T2["T-2: failed servis / disk dolu"]
|
||||
|
|
|
|||
|
|
@ -1,43 +1,41 @@
|
|||
# 20 — Saha Teknisyeni Runbook
|
||||
|
||||
> Kısa özet: Sahada cihaz başına giden teknisyenin el kitabı. Tek akış: USB'yi tak → Ubuntu'yu kur → `sudo bf` → bayi numarasını gir → sonucu gör. Komut ezberi istenmez: kurulum, durum ve destek paketi grafik arayüzdeki düğmelerle yapılır; her adımda "ne göreceksin, ne yazacaksın" vardır.
|
||||
> Kısa özet: Sahada cihaz başına giden teknisyenin el kitabı. Tek akış: USB'yi tak → kur → bayi numarasını gir → READY'yi gör → çık. Komut ezberi istenmez; her adımda "ne göreceksin, ne yazacaksın" vardır.
|
||||
|
||||
- Dosya: `docs/20-FIELD-TECHNICIAN-RUNBOOK.md`
|
||||
- İlgili kararlar: `24-DECISION-LOG.md#K-09` (USB → kurucu → bayi no), `#K-12` (bayi no → `BF-<no>`), `#K-14` (`bf-status`, support-bundle), `#K-16` (offline kurulum)
|
||||
- İlgili dokümanlar: `33-OPERATOR-CONSOLE.md` (arayüz rehberi), `27-OFFLINE-PROVISIONING.md` (paket deposu)
|
||||
- İlgili kararlar: `24-DECISION-LOG.md#K-09` (USB → script → bayi no → READY), `#K-12` (bayi no → `BF-<no>`), `#K-14` (`bf-status`, support-bundle)
|
||||
- Durum: [ ] Taslak
|
||||
|
||||
---
|
||||
|
||||
## 1. Amaç
|
||||
|
||||
Teknisyenin sahada tek başına, telefonsuz bile cihazı teslim edilebilir hale getirmesi. Bu dosya "neden" anlatmaz, "ne yap" söyler. Neden merak eden 01'e bakar.
|
||||
Teknisyenin sahada tek başına, telefonsuz bile cihazı READY hale getirmesi. Bu dosya "neden" anlatmaz, "ne yap" söyler. Neden merak eden 01'e bakar.
|
||||
|
||||
## 2. Kapsam
|
||||
|
||||
- Kapsam içi: USB ile sıfır kurulum, grafik arayüzü açma, bayi no girişi, kurulum sonucunu doğrulama, arızalı cihazda ilk 3 hareket, merkeze ne zaman telefon açılacağı.
|
||||
- Kapsam içi: USB ile sıfır kurulum, bayi no girişi, READY kontrolü, arızalı cihazda ilk 3 hareket, merkeze ne zaman telefon açılacağı.
|
||||
- Kapsam dışı: merkez onayları (21), arıza teşhis tablosu detayı (19 — sadece yönlendirme), update dalgaları (10).
|
||||
|
||||
## 3. Kararlar
|
||||
|
||||
```text
|
||||
KARAR: Teknisyen akışı 4 adımdır: USB → Ubuntu kur → `sudo bf` ile kurulum (bayi no) → sonucu gör. Grafik arayüz tek giriş noktasıdır; terminal konsolu (`sudo bf --tui`) yalnız grafik ekran veya tkinter yoksa kullanılan yedektir. Teknisyen hostname, IP, anahtar, paket yolu veya config dosyası ile uğraşmaz; paketler depoyla gelir ve kurulumda internet gerekmez.
|
||||
GEREKÇE: K-09/K-16'nın hedef akışı; insan hatası en çok elle config ve ezberlenen komutta olur. Teknisyenin tek manuel girdisi 8 haneli bayi numarasıdır (K-12).
|
||||
ALTERNATİF: Teknisyene tam Linux eğitimi + manuel kurulum — 700 cihazda standardizasyon bozulur; elendi. Yalnız bash menülü kurulum — grafik arayüz varken gereksiz terminal bilgisi ister; yedek yol olarak korundu.
|
||||
RİSK: Depo kopyası eski sürüm kalır; azaltma: repo sürüm etiketi + merkezden "şu sürümden eski kopyayı kullanma" duyurusu.
|
||||
KARAR: Teknisyen akışı 4 adımdır: USB → kur → bayi no → READY. Teknisyen hostname, IP, anahtar, config dosyası ile uğraşmaz; hepsini `blueforce-install.sh` yapar.
|
||||
GEREKÇE: K-09'un hedef akışı; insan hatası en çok elle config'de olur. Teknisyenin tek manuel girdisi 8 haneli bayi numarasıdır (K-12).
|
||||
ALTERNATİF: Teknisyene tam Linux eğitimi + manuel kurulum — 700 cihazda standardizasyon bozulur; elendi.
|
||||
RİSK: Script USB'si eski sürüm kalır; azaltma: USB etiketinde sürüm + merkezden "şu sürümden eski USB'yi kullanma" duyurusu.
|
||||
MALİYET: Ücretsiz.
|
||||
LİSANS: Yok.
|
||||
```
|
||||
|
||||
## 4. Neden Bu Karar?
|
||||
|
||||
Teknisyenin işi "bilgisayarcılık" değil "bayi cihazını çalışır teslim etmek"tir. Karar, teknisyenin dikkatini tek kritik noktaya toplar: bayi numarasını doğru girmek. Geri kalan her şey uygulama + merkez otomasyonudur. Bu yüzden bu dosya kısa cümlelerle, emir kipiyle yazılır.
|
||||
Teknisyenin işi "bilgisayarcılık" değil "bayi cihazını çalışır teslim etmek"tir. Karar, teknisyenin dikkatini tek kritik noktaya toplar: bayi numarasını doğru girmek. Geri kalan her şey script + merkez otomasyonudur. Bu yüzden bu dosya kısa cümlelerle, emir kipiyle yazılır.
|
||||
|
||||
## 5. Alternatifler
|
||||
|
||||
| Alternatif | Artı | Eksi | Sonuç |
|
||||
|---|---|---|---|
|
||||
| Grafik arayüz (`sudo bf`) | Tek düğme, komut ezberi yok, onay görünür | Grafik katman gerekir | **Seçildi** |
|
||||
| Detaylı Linux kılavuzu | Bilgili teknisyen | Uzun, hata açık, herkes okumaz | Elendi |
|
||||
| Merkezden uzaktan kurulum (teknisyensiz) | Saha maliyeti yok | İlk kurulumda cihazda internet/VPN yok | Elendi (ilk kurulum sahada) |
|
||||
|
||||
|
|
@ -45,21 +43,19 @@ Teknisyenin işi "bilgisayarcılık" değil "bayi cihazını çalışır teslim
|
|||
|
||||
- Yeni teknisyen 1 saatlik eğitimle sahaya çıkar.
|
||||
- Her cihaz aynı adımla kurulur; "ustalık farkı" kapanır.
|
||||
- Kurulum internetsiz çalışır: paket seti depodan gelir, hiçbir şey indirilmez.
|
||||
|
||||
## 7. Dezavantajlar
|
||||
|
||||
- Uygulamanın yapmadığını teknisyen de yapamaz; olağandışı durumda merkeze bağımlıdır (bilerek böyle).
|
||||
- Depo kopyası (paket setiyle birlikte ~888 MB) fiziksel/lojistik takip ister.
|
||||
- Script'in yapmadığını teknisyen de yapamaz; olağandışı durumda merkeze bağımlıdır (bilerek böyle).
|
||||
- USB medyası fiziksel lojistik ister (sürüm takibi).
|
||||
|
||||
## 8. Riskler
|
||||
|
||||
| Risk | Olasılık | Etki | Azaltma |
|
||||
|---|---|---|---|
|
||||
| Bayi no yanlış girilir | Orta | Yüksek | Arayüz `BF-<no>`'yu gösterir, teknisyen bayiye onaylatır |
|
||||
| Eski depo kopyası ile kurulum | Orta | Orta | Repo sürüm etiketi + kurucu başlangıçta depoyu ve paket sayısını söyler |
|
||||
| Grafik arayüz açılmaz (ekran/tkinter) | Orta | Orta | `sudo bf --tui` yedeği; sorun merkeze bildirilir |
|
||||
| Sonuç görülmeden sahadan çıkılır | Düşük | Yüksek | Kontrol listesi imzalanmadan iş kapanmaz |
|
||||
| Bayi no yanlış girilir | Orta | Yüksek | Script ekranda `BF-<no>`'yu gösterir, teknisyen bayiye onaylatır |
|
||||
| Eski USB ile kurulum | Orta | Orta | USB sürüm etiketi + kurucu açılışta sürümü söyler |
|
||||
| READY görülmeden sahadan çıkılır | Düşük | Yüksek | Kontrol listesi imzalanmadan iş kapanmaz |
|
||||
|
||||
## 9. Uygulama Planı
|
||||
|
||||
|
|
@ -73,109 +69,82 @@ Teknisyenin işi "bilgisayarcılık" değil "bayi cihazını çalışır teslim
|
|||
|
||||
> Göreceğin: Ubuntu kurulum ekranı. Bunu görmüyorsan: USB tam takılı mı, BIOS boot sırası USB mi? Olmazsa merkeze telefon aç.
|
||||
|
||||
**ADIM 2 — Ubuntu'yu kur ve depo kopyasını getir.**
|
||||
**ADIM 2 — Ubuntu'yu kur.**
|
||||
|
||||
1. Ekrandaki kurulumu varsayılanlarla tamamla (dil: Türkçe, disk: tamamını kullan).
|
||||
2. Kurulum bitince USB'yi çıkarma, bilgisayarı yeniden başlat.
|
||||
3. Repo kopyasını cihaza getir (merkezin söylediği yolla: `git clone` — paketler Git LFS ile birlikte gelir — veya hazır kopya `/opt/blueforce/offline-repo` altına konur).
|
||||
|
||||
> Paketler repoyla birlikte gelir; **internetten hiçbir şey indirilmez**.
|
||||
|
||||
**ADIM 3 — Grafik arayüzü aç, bayi numarasını gir, kurulumu başlat.**
|
||||
**ADIM 3 — Kurucu scripti çalıştır, bayi numarasını gir.**
|
||||
|
||||
1. Terminali aç, şunu yaz:
|
||||
|
||||
```bash
|
||||
sudo bf
|
||||
sudo ./blueforce-install.sh
|
||||
```
|
||||
|
||||
2. Pencere açılır: başlık **Blueforce Field OS — Yönetim**. (Ekran yoksa veya tkinter yoksa uygulama Türkçe uyarı verir; o zaman `sudo bf --tui` yaz — §D.)
|
||||
3. Üst çubuktaki **Hedef > Bayi no (8 hane)** alanına **8 haneli bayi numarasını** yaz. Faturadaki/sistemdeki numarayı kullan. Örnek: `12010193`.
|
||||
4. **Kurulum** sekmesi → **`Bu cihazı kur`**.
|
||||
5. Arayüz komutu ekranda gösterir ve onay ister. `BF-12010193` görünüyor mu? Doğruysa onayla; yanlışsa iptal et ve numarayı düzelt.
|
||||
2. Script senden **8 haneli bayi numarasını** ister. Faturadaki/sistemdeki numarayı yaz, Enter'a bas. Örnek: `12010193`.
|
||||
3. Script ekranda şunu gösterecek:
|
||||
|
||||
```text
|
||||
Arayüzden: sudo bf → Hedef: Bayi no (8 hane) → Kurulum → "Bu cihazı kur"
|
||||
Komutla (yedek):
|
||||
sudo bf --tui # terminal konsolu; Kurulum menüsünden aynı akış
|
||||
sudo ./scripts/install/blueforce-install.sh --dealer-id 12010193
|
||||
Device ID: BF-12010193
|
||||
Hostname: bf-12010193
|
||||
```
|
||||
|
||||
6. Numarayı bayiye sesli onaylat: "Cihaz numaranız BF-12010193, doğru mu?"
|
||||
4. Numarayı bayiye sesli onaylat: "Cihaz numaranız BF-12010193, doğru mu?" Yanlışsa scriptten çık, tekrar çalıştır.
|
||||
|
||||
**ADIM 4 — Sonucu gör, çık.**
|
||||
**ADIM 4 — READY'yi gör, çık.**
|
||||
|
||||
1. Kurulum bitene kadar bekle (kapatma, fişi çekme). Cihazın açık kalması şart.
|
||||
2. Sonucu gör:
|
||||
1. Script bitene kadar bekle (kapatma, fişi çekme).
|
||||
2. Sonunda şunu çalıştır:
|
||||
|
||||
```text
|
||||
Arayüzden: `Durum` düğmesi (basit mod) → Durum özeti ya da Kurulum sekmesi → "Kurulum modül durumu"
|
||||
Komutla (yedek): bf-status
|
||||
```bash
|
||||
bf-status
|
||||
```
|
||||
|
||||
3. **`PROVISIONED_OFFLINE`** görmen normaldir: kurulum yerelde tamamlandı, cihaz internetsiz kuruldu. Bu durumda cihaz `READY` değildir.
|
||||
4. İnternet geldiğinde merkezden tek-kullanımlık enrollment token iste ve 29'daki adımı uygula.
|
||||
5. Token sonrası **ENROLLED** görünür; WireGuard, remote ve monitoring merkezi doğrulaması bitince **READY** görürsün.
|
||||
6. READY sonrası kontrol listesini doldur (§12), sahadan çık.
|
||||
3. Offline medya ile kurulumda önce **PROVISIONED_OFFLINE** görmen normaldir; bu durumda cihaz READY değildir. İnternet geldiğinde merkezden tek-kullanımlık enrollment token iste ve 29'daki adımı uygula.
|
||||
4. Token sonrası **ENROLLED** görünür; WireGuard, remote ve monitoring merkezi doğrulaması bitince **READY** görmelisin.
|
||||
5. READY sonrası kontrol listesini doldur (§12), sahadan çık.
|
||||
|
||||
### B. Arızalı cihaza gittin — ilk 3 hareket
|
||||
|
||||
1. Durumu oku:
|
||||
|
||||
```text
|
||||
Arayüzden: sudo bf → `Durum` düğmesi (Durum özeti)
|
||||
Komutla (yedek): bf-status
|
||||
```
|
||||
|
||||
Kırmızı satır hangisi? Not al.
|
||||
1. `bf-status` çalıştır. Kırmızı satır hangisi? Not al.
|
||||
2. Bilgisayarı bir kez yeniden başlat. Düzelirse READY'yi gör, çık.
|
||||
3. Düzelmezse destek paketini al, merkeze gönder:
|
||||
3. Düzelmezse support paketini al, merkeze gönder:
|
||||
|
||||
```text
|
||||
Arayüzden: sudo bf → Detaylı mod → Araçlar sekmesi → "Destek paketi oluştur"
|
||||
Komutla (yedek): bf-support-bundle --out /tmp/bf-<bayi-no>-bundle.tar.gz
|
||||
```bash
|
||||
bf-support-bundle --out /tmp/bf-<bayi-no>-bundle.tar.gz
|
||||
```
|
||||
|
||||
Paketi merkeze ilet (telefonla nasıl göndereceğin söylenir), merkez sana söylemeden başka komut çalıştırma.
|
||||
|
||||
### C. Merkeze telefon açma kuralları
|
||||
|
||||
Hemen ara: sonucu alamıyorsan, aynı arıza 2 cihazda üst üste çıktıysa, donanım kırık/yanık kokusu varsa, bayi numarasından emin değilsen.
|
||||
Arama: cihaz başında ol, `BF-<no>`'yu ve durum özetini/`bf-status` çıktısını hazır tut.
|
||||
|
||||
### D. Grafik arayüz açılmıyor — yedek yol
|
||||
|
||||
| Belirti | Ne yap |
|
||||
|---|---|
|
||||
| "Grafik ekran bulunamadı" / SSH oturumu | `sudo bf --tui` yaz; aynı işlemler terminal menüsünde numaralarla yürür |
|
||||
| "tkinter bulunamadı" | `sudo bf --tui` ile devam et ve merkeze bildir; `python3-tk` paketi kurulum depounda pinlidir (19 §T-10) |
|
||||
| Pencere açıldı ama dondu | Pencereyi kapat, `sudo bf --tui` ile devam et, merkeze bildir |
|
||||
Hemen ara: READY alamıyorsan, aynı arıza 2 cihazda üst üste çıktıysa, donanım kırık/yanık kokusu varsa, bayi numarasından emin değilsen.
|
||||
Arama: cihaz başında ol, `BF-<no>`'yu ve `bf-status` çıktısını hazır tut.
|
||||
|
||||
## 10. Test Planı
|
||||
|
||||
| Test | Beklenen sonuç | Ortam |
|
||||
|---|---|---|
|
||||
| Sıfır teknisyen 4 adımı desteksiz yapar | Hedef teslim durumu < hedef süre | LAB(2) |
|
||||
| Yanlış bayi no girilir | Uygulama uyarır, komut üretilmez/çalışmaz | LAB(2) |
|
||||
| Ekransız oturumda `sudo bf` | Türkçe yönlendirme + `sudo bf --tui` önerisi, exit 3 | LAB(2) |
|
||||
| Depo kopyası olmayan cihazda kurulum | Türkçe hata + aranan yollar + çıkış nedeni, sistem değişmez | LAB(2) |
|
||||
| Elektrik kesintisi simülasyonu sonrası durum | Kurulum kaldığı yerden tamamlanır; durum doğru raporlanır | LAB(2) |
|
||||
| Sıfır teknisyen 4 adımı desteksiz yapar | READY < hedef süre | LAB(2) |
|
||||
| Yanlış bayi no girilir | Script uyarır, kuruluma devam etmez | LAB(2) |
|
||||
| Elektrik kesintisi simülasyonu sonrası `bf-status` | READY döner | LAB(2) |
|
||||
|
||||
## 11. Rollback
|
||||
|
||||
Teknisyen rollback yapmaz. Kurulum yarıda kesildiyse: `sudo bf` → Kurulum sekmesi → **`Başarısız kuruluma devam et (--resume)`** (komutla yedek: aynı kurucu `--resume` bayrağıyla). İkinci denemede de olmazsa merkeze telefon aç — merkez 17-RECOVERY'den seviyeyi seçer.
|
||||
Teknisyen rollback yapmaz. Kurulum yarıda kesildiyse: baştan başla (ADIM 1). İkinci denemede de olmazsa merkeze telefon aç — merkez 17-RECOVERY'den seviyeyi seçer.
|
||||
|
||||
## 12. Kontrol Listesi
|
||||
|
||||
- [ ] Depo kopyası/checkout sürümü güncel (etiket + merkez duyurusu eşleşiyor).
|
||||
- [ ] USB sürümü güncel (etiket + merkez duyurusu eşleşiyor).
|
||||
- [ ] `BF-<no>` bayiye onaylatıldı.
|
||||
- [ ] Kurulum sonucu görüldü (`PROVISIONED_OFFLINE` normaldir; READY için §A/ADIM 4-5).
|
||||
- [ ] `bf-status` → READY görüldü.
|
||||
- [ ] Cihaz fişe + internete bağlı bırakıldı.
|
||||
- [ ] İş formu dolduruldu (bayi no, tarih, teknisyen adı).
|
||||
|
||||
## 13. Açık Sorular
|
||||
|
||||
- [ ] Depo kopyasının sahaya taşınma/sürüm takip yöntemi (git clone + LFS mı, hazır kopya mı) (sahibi: merkezi admin, 21).
|
||||
- [ ] Kurulum USB'sinin dağıtım/sürüm takip yöntemi (sahibi: merkezi admin, 21).
|
||||
- [ ] İş formu kağıt mı mobil mi (sahibi: 25-ROADMAP).
|
||||
- [ ] Hedef kurulum süresi (öneri: P2'de ölçülecek).
|
||||
|
||||
|
|
@ -186,15 +155,11 @@ Teknisyen rollback yapmaz. Kurulum yarıda kesildiyse: `sudo bf` → Kurulum sek
|
|||
```mermaid
|
||||
flowchart TB
|
||||
USB["USB tak → aç"] --> KUR["Ubuntu kur"]
|
||||
KUR --> DEPO["Depo kopyasını getir<br/>(paketler LFS ile gelir, indirme yok)"]
|
||||
DEPO --> BF["sudo bf"]
|
||||
BF --> EKRAN{"Grafik ekran +<br/>python3-tk var mı?"}
|
||||
EKRAN -->|Hayır| TUI["sudo bf --tui<br/>(yedek terminal konsolu)"]
|
||||
EKRAN -->|Evet| NO["Hedef: Bayi no (8 hane)"]
|
||||
TUI --> NO
|
||||
NO --> ONAY["Arayüz komutu gösterir + onay<br/>BF-no'yu bayiye onaylat"]
|
||||
ONAY --> BEKLE["Kurulum bitsin<br/>(kapatma / fişi çekme)"]
|
||||
BEKLE --> DURUM["Durum: PROVISIONED_OFFLINE / ENROLLED / READY"]
|
||||
DURUM -->|"READY"| CIK["Formu doldur → çık"]
|
||||
DURUM -->|"sorun var"| TEL["Destek paketi + merkeze telefon aç"]
|
||||
KUR --> SCR["sudo ./blueforce-install.sh"]
|
||||
SCR --> NO["Bayi no gir<br/>(8 hane)"]
|
||||
NO --> ONAY["BF-no'yu bayiye onaylat"]
|
||||
ONAY --> BEKLE["Script bitsin"]
|
||||
BEKLE --> READY["bf-status → READY?"]
|
||||
READY -->|evet| CIK["Formu doldur → çık"]
|
||||
READY -->|hayır| TEL["Merkeze telefon aç"]
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1,28 +1,27 @@
|
|||
# 21 — Merkezi Yönetici Runbook
|
||||
|
||||
> Kısa özet: Merkezdeki yöneticinin el kitabı: hangi işlemi kim onaylar, update'i kim başlatır, dalga kapıları nasıl açılır, teknisyen ne zaman sahaya sürülür. Yetki ve sıra bu dosyadadır. Filo işlemleri grafik arayüzden (`sudo bf` → `Cihaz işlemleri`) yürütülür; komut satırı karşılıkları yedek/otomasyon yoludur.
|
||||
> Kısa özet: Merkezdeki yöneticinin el kitabı: hangi işlemi kim onaylar, update'i kim başlatır, dalga kapıları nasıl açılır, teknisyen ne zaman sahaya sürülür. Yetki ve sıra bu dosyadadır.
|
||||
|
||||
- Dosya: `docs/21-CENTRAL-ADMIN-RUNBOOK.md`
|
||||
- İlgili kararlar: `24-DECISION-LOG.md#K-06` (Ansible/Semaphore), `#K-11` (onay zinciri + dalgalar), `#K-13` (anahtar dağıtımı)
|
||||
- İlgili dokümanlar: `33-OPERATOR-CONSOLE.md` (arayüz rehberi), `10-UPDATE-AND-ROLLBACK-POLICY.md` (dalga politikası), `20-FIELD-TECHNICIAN-RUNBOOK.md` (saha)
|
||||
- Durum: [ ] Taslak
|
||||
|
||||
---
|
||||
|
||||
## 1. Amaç
|
||||
|
||||
Merkezde "kim, neyi, hangi sırayla yapar" sorusunu kapatmak. Update'i kim başlatır, dalgayı kim onaylar, acil durumda kim karar verir — hepsi burada yazar, kriz anında aranmaz. İşlemler tek arayüzde toplanır: `sudo bf` (grafik) veya `sudo bf --tui` (yedek terminal konsolu).
|
||||
Merkezde "kim, neyi, hangi sırayla yapar" sorusunu kapatmak. Update'i kim başlatır, dalgayı kim onaylar, acil durumda kim karar verir — hepsi burada yazar, kriz anında aranmaz.
|
||||
|
||||
## 2. Kapsam
|
||||
|
||||
- Kapsam içi: rol ve onay yetkileri, update başlatma akışı, dalga kapı prosedürü, arayüz üzerinden filo işlemi yürütme, anahtar/erişim yönetimi, acil durum yetkisi, günlük/haftalık rutinler.
|
||||
- Kapsam dışı: tek cihaz kurulum adımları (20), komut-seviyesi teşhis (19), kurtarma seviye tablosu (17 — buradan çağrılır), merkez sunucusunun kurulumu (arayüzde yalnız "Merkez hazırlığı" denetimleri vardır).
|
||||
- Kapsam içi: rol ve onay yetkileri, update başlatma akışı, dalga kapı prosedürü, anahtar/erişim yönetimi, acil durum yetkisi, günlük/haftalık rutinler.
|
||||
- Kapsam dışı: tek cihaz kurulum adımları (20), komut-seviyesi teşhis (19), kurtarma seviye tablosu (17 — buradan çağrılır).
|
||||
|
||||
## 3. Kararlar
|
||||
|
||||
```text
|
||||
KARAR: Update'i yalnızca merkezi yönetici başlatır; teknisyen, bayi veya otomatik zamanlayıcı update tetikleyemez. Her dalga geçişi açık onay gerektirir: arayüzden çalıştırıldığında "production" yazma adımı + production ek onayı, gündelik/sürüm kapsamlı işlemlerde kapı sözcüğü; Semaphore iş akışı kullanılıyorsa kapı adımı Semaphore'dadır.
|
||||
GEREKÇE: K-11 "onaysız update yasak" ilkesinin operasyonel karşılığıdır; tek başlatma noktası = denetlenebilirlik. Otomatik tetikleyici olmaması, zamanlanmış sürprizleri engeller. Onay olmadan komut üretilmez: arayüz komutu önce gösterir, kapı adımını geçmeyen çağrıda bayrağı kendiliğinden eklemez.
|
||||
KARAR: Update'i yalnızca merkezi yönetici başlatır; teknisyen, bayi veya otomatik zamanlayıcı update tetikleyemez. Her dalga geçişi açık onay (Semaphore kapı adımı + kayıt) gerektirir.
|
||||
GEREKÇE: K-11 "onaysız update yasak" ilkesinin operasyonel karşılığıdır; tek başlatma noktası = denetlenebilirlik. Otomatik tetikleyici olmaması, zamanlanmış sürprizleri engeller.
|
||||
ALTERNATİF: Takvimli otomatik dalga başlatma — onay kaydı zayıflar, arızada "kim başlattı" belirsizleşir; elendi.
|
||||
RİSK: Yönetici izindeyken update kilitlenir; azaltma: en az 2 onay yetkilisi tanımlanır (asıl + vekil).
|
||||
MALİYET: Ücretsiz.
|
||||
|
|
@ -40,7 +39,7 @@ LİSANS: Yok.
|
|||
|
||||
## 4. Neden Bu Karar?
|
||||
|
||||
700 cihazda en tehlikeli cümle "ben başlattım sandım"dır. Başlatma yetkisini tek role toplamak, hem hatayı hem suçu önler: hata olursa kayıttan bulunur, suçlama olursa kayıt konuşur. Vekil kuralı, tek kişiye bağımlılığı kaldırır. Arayüz bu disiplini görünür kılar: dalga kapsamlı her işlemde komut, bayraklarıyla birlikte ekranda gösterilir, production dalgası için `production` yazılmadan komut çalışmaz; her karar `/var/log/blueforce-console.log` (mod `600`) dosyasına düşer.
|
||||
700 cihazda en tehlikeli cümle "ben başlattım sandım"dır. Başlatma yetkisini tek role toplamak, hem hatayı hem suçu önler: hata olursa kayıttan bulunur, suçlama olursa kayıt konuşur. Vekil kuralı, tek kişiye bağımlılığı kaldırır.
|
||||
|
||||
## 5. Alternatifler
|
||||
|
||||
|
|
@ -49,28 +48,24 @@ LİSANS: Yok.
|
|||
| Herkes update başlatabilir | Hızlı | Onaysız yayılım, denetimsizlik | Elendi |
|
||||
| Tam otomatik pipeline | Eforsuz | Politika ihlali (K-11) | Elendi |
|
||||
| Tek onay yetkilisi | Net | İzin/hastalıkta kilit | Elendi (asıl+vekil) |
|
||||
| Yalnız serbest `ansible-playbook` komutu | Esnek | Kapı bayrakları elle yazılır, atlanabilir | Elendi (arayüz kapıyı bayrakla bağlar) |
|
||||
|
||||
## 6. Avantajlar
|
||||
|
||||
- Her update'in "kim başlattı, kim onayladı, ne zaman" kaydı vardır (konsol denetim günlüğü).
|
||||
- Her update'in "kim başlattı, kim onayladı, ne zaman" kaydı vardır.
|
||||
- Acil durumda bile sıra korunur; hız, sıranın içinde ayarlanır.
|
||||
- Hedef seçimi tek yerden yapılır: tek cihaz (bayi no), dalga grubu (lab, pilot_1, pilot_2, wave_1, wave_2, production) veya tüm filo.
|
||||
|
||||
## 7. Dezavantajlar
|
||||
|
||||
- Onay adımı update'i yavaşlatır (bilerek; hız 25-ROADMAP'ta acil yoluyla dengelenir).
|
||||
- Kapı adımı atlanırsa (serbest CLI ile run) politika kağıtta kalır — teknik zorunluluk şarttır.
|
||||
- Arayüz grafik katman gerektirir; merkez sunucusunda yoksa `sudo bf --tui` kullanılır.
|
||||
- Semaphore kapı adımı atlanırsa politika kağıtta kalır — teknik zorunluluk şarttır.
|
||||
|
||||
## 8. Riskler
|
||||
|
||||
| Risk | Olasılık | Etki | Azaltma |
|
||||
|---|---|---|---|
|
||||
| Kapı adımı bypass edilir (arayüz dışı CLI run) | Orta | Yüksek | Semaphore/arayüz dışı prod run yasaktır; denetim günlüğü izlenir |
|
||||
| Kapı adımı bypass edilir (CLI'dan direkt run) | Orta | Yüksek | Semaphore dışı prod run'ı yasaktır; denetim logu izlenir |
|
||||
| İki yetkili de ulaşılamaz | Düşük | Orta | Acil iletişim zinciri + önceden tanımlı duraklatma (devam etme, durdur) |
|
||||
| Anahtar sızıntısı | Düşük | Yüksek | Per-admin anahtar iptali + rotasyon (K-13) |
|
||||
| Yanlış hedefe işlem (grup/tüm filo) | Orta | Yüksek | Hedef arayüzde tek tek seçilir; `--limit` komutta görünür, onay istenir |
|
||||
|
||||
## 9. Uygulama Planı
|
||||
|
||||
|
|
@ -86,34 +81,16 @@ LİSANS: Yok.
|
|||
### Standart update akışı (yönetici gözüyle)
|
||||
|
||||
1. Update talebi gelir (güvenlik bülteni / MEG sürümü / OS yaması) → etki + geri alma planı raporlanır.
|
||||
2. Onay yetkilisi LAB'ı başlatır: Semaphore'da job + kayıt (veya arayüzden dalga işlemi).
|
||||
2. Onay yetkilisi LAB'ı başlatır: Semaphore'da job + kayıt.
|
||||
3. LAB çıkış kriteri tuttuysa P1 → P2 → W1 → W2 → PROD, her kapıda açık onay.
|
||||
4. Herhangi bir dalgada halt kuralı (18) tetiklenirse: yayılım DURUR, 17-L3 işletilir, kök neden bulunmadan kapı açılmaz.
|
||||
5. PROD bitiminde kapanış kaydı (başarı/arıza sayısı, süre).
|
||||
|
||||
```text
|
||||
Arayüzden (merkez operatörü):
|
||||
sudo bf → Detaylı mod → Cihaz işlemleri sekmesi
|
||||
→ işlemi seç (örn. "Kontrollü yeniden başlatma" / "Onaylı paket güncellemesi")
|
||||
→ Hedef: dalga grubu (lab, pilot_1, pilot_2, wave_1, wave_2, production)
|
||||
→ kapı adımı: production için 'production' yazmak ZORUNLU
|
||||
→ komut ekranda gösterilir → onay → çalışır
|
||||
|
||||
Komutla (yedek / otomasyon):
|
||||
ansible-playbook -i ansible/inventory/... ansible/playbooks/bf-reboot.yml \
|
||||
--limit wave_p1 -e operation_wave=wave_1 -e operation_confirmed=true
|
||||
# production_override / allow_production_reboot yalnız production ek onayıyla eklenir.
|
||||
# Kapı kuralı: önceki dalga sağlık kapısını geçmediyse çalıştırılmaz (10).
|
||||
```
|
||||
|
||||
Planlama/denetim komutlarının arayüz karşılıkları:
|
||||
|
||||
```text
|
||||
Arayüzden: sudo bf → Merkez hazırlığı sekmesi
|
||||
(envanter hedefleri ve dalga/cihaz sayıları, PLACEHOLDER denetimi,
|
||||
merkez uç noktaları, hazırlık kontrol listesi — hepsi salt-okunur)
|
||||
Komutla (yedek): sudo bf --tui → Merkez hazırlığı menüsü
|
||||
admin/bf-menu --list-targets # yedek bash menüsü
|
||||
```bash
|
||||
# örnek: onaylı dalga run (operatör, onay sonrası)
|
||||
ansible-playbook playbooks/update.yml --limit wave_p1
|
||||
# örnek: kapı kontrolü — onaysız PROD engeli (ilke; teknik karşılığı Semaphore'da)
|
||||
# PROD limiti yalnızca "prod-onay" etiketli job ile koşar
|
||||
```
|
||||
|
||||
### Anahtar ve erişim yönetimi
|
||||
|
|
@ -124,39 +101,34 @@ Komutla (yedek): sudo bf --tui → Merkez hazırlığı menüsü
|
|||
|
||||
### Günlük / haftalık rutinler
|
||||
|
||||
- Günlük (operatör, 10 dk): Uptime Kuma UP/DOWN, Prometheus `up` == 0 listesi, gece reboot olanlar, yedek job durumu. Cihaz durumu için arayüzden `Durum` düğmesi ya da `Cihaz işlemleri > Kurulum fazı raporu`.
|
||||
- Günlük (operatör, 10 dk): Uptime Kuma UP/DOWN, Prometheus `up` == 0 listesi, gece reboot olanlar, yedek job durumu.
|
||||
- Haftalık (yönetici, 30 dk): dalga takvimi, açık halt'lar, anahtar/envanter uyumsuzlukları, `PROVISIONED_OFFLINE`/`ENROLLED` bekleyen cihaz kuyruğu, release manifest/rollback kanıtı ve L9 tatbikat sayacı (27/29/30).
|
||||
|
||||
## 10. Test Planı
|
||||
|
||||
| Test | Beklenen sonuç | Ortam |
|
||||
|---|---|---|
|
||||
| Onaysız PROD run denemesi | Engellenir (`production` yazılmadan komut çalışmaz) + denetim günlüğüne yazılır | Merkez test |
|
||||
| Onaysız PROD run denemesi | Engellenir + log düşer | Merkez test |
|
||||
| Semaphore kapalıyken Ansible CLI run | Onaylı iş CLI'dan koşar (K-06) | LAB(2) |
|
||||
| Vekil ile dalga onayı | Kayıtta vekil adı görünür | Merkez test |
|
||||
| Arayüzden dalga hedefi seçimi | Komutta doğru `--limit` görünür, yanlış hedefte komut üretilmez | Merkez test |
|
||||
| Grafik arayüz yokken yönetim işlemleri | `sudo bf --tui` ile aynı işlemler yürütülür | LAB(2) SSH |
|
||||
|
||||
## 11. Rollback
|
||||
|
||||
1. Hatalı dalga: 17-L3 + 10-UPDATE rollback zinciri; kapı bir sonraki dalgaya kapatılır.
|
||||
2. Hatalı onay: aynı yetkili (veya vekil) durdurma kararı verir; "devam" kararı verilemez, yalnızca "dur + geri al".
|
||||
3. Arayüzden başlatılan yanlış kapsamlı işlem: komut ekranda ve denetim günlüğünde hedefiyle kayıtlıdır; kapsam bu kayıttan doğrulanıp geri alma adımı planlanır.
|
||||
|
||||
## 12. Kontrol Listesi
|
||||
|
||||
- [ ] Asıl + vekil isimle tanımlı ve iletişim bilgileri güncel.
|
||||
- [ ] Semaphore'da PROD kapı adımı teknik olarak zorunlu; arayüzde production için 'production' yazma adımı çalışıyor.
|
||||
- [ ] Her dalga onayı kayıtlı (kim, ne zaman, hangi sürüm) — `/var/log/blueforce-console.log` mod `600`.
|
||||
- [ ] Semaphore'da PROD kapı adımı teknik olarak zorunlu.
|
||||
- [ ] Her dalga onayı kayıtlı (kim, ne zaman, hangi sürüm).
|
||||
- [ ] Ayrılan personelin anahtarı kaldırıldı.
|
||||
- [ ] Merkez operatörleri grafik arayüzü (`sudo bf`) ve yedek terminal konsolunu (`sudo bf --tui`) biliyor.
|
||||
|
||||
## 13. Açık Sorular
|
||||
|
||||
- [ ] Acil tanımı eşikleri (CVSS/aktif sömürü) — 10-UPDATE ile ortak onay (sahibi: yönetici).
|
||||
- [ ] Kapanış raporu formatı ve saklama süresi (sahibi: 25-ROADMAP).
|
||||
- [ ] Read-only yönetim panosu kapsamı (sahibi: 14-MONITORING yazarı).
|
||||
- [ ] Arayüzün merkez sunucusunda (`sudo bf --tui` mi, grafik mi) varsayılan kullanımı (sahibi: 33 + merkez ekibi).
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -167,10 +139,7 @@ flowchart TB
|
|||
TALEP["Update talebi<br/>(güvenlik / MEG / OS)"] --> KAYIT["Değişiklik kaydı<br/>kapsam + geri alma planı"]
|
||||
KAYIT --> ONAY{"Onay yetkilisi<br/>(asıl veya vekil)"}
|
||||
ONAY -->|Ret| KAPANIR["Kapanış kaydı (ret)"]
|
||||
ONAY -->|Onay| UI["sudo bf → Cihaz işlemleri<br/>hedef: dalga grubu"]
|
||||
UI --> KAPI0{"Kapı adımı<br/>production ise 'production' yaz"}
|
||||
KAPI0 -->|Geçmedi| DUR0["Komut çalışmaz<br/>(denetim günlüğü: CANCEL)"]
|
||||
KAPI0 -->|Geçti| LAB["LAB(2) → P1(5) → P2(20)"]
|
||||
ONAY -->|Onay| LAB["LAB(2) → P1(5) → P2(20)"]
|
||||
LAB --> KAPI{"Sağlık kapısı temiz mi?"}
|
||||
KAPI -->|Halt| DUR["Yayılım DURUR → 17-L3 rollback"]
|
||||
KAPI -->|Temiz| WAVE["W1(50) → W2(100) → PROD(~523)"]
|
||||
|
|
|
|||
|
|
@ -1,102 +1,83 @@
|
|||
# 27 — Offline Provisioning
|
||||
|
||||
> Kısa özet: Paketler **git deposunun içindedir** (`provisioning/offline-repo/packages/`, 1321 `.deb`, ~888 MB, Git LFS ile takip edilir). Saha kurulumu internet **gerektirmez** ve kuran kişi **hiçbir şey indirmez**: `sudo bf` → Kurulum sekmesi → "Bu cihazı kur" → 8 haneli bayi no → onay. Bu yol yalnız `PROVISIONED_OFFLINE` durumuna getirir; cihaz, tek kullanımlık enrollment token ve merkezi kanallar doğrulanmadan `ENROLLED` veya `READY` olmaz.
|
||||
> Kısa özet: İnternet yokken Field OS kurulumu ve yerel paket yüklemesi yapılabilir. Bu yol yalnız `PROVISIONED_OFFLINE` durumuna getirir; cihaz, tek kullanımlık enrollment token ve merkezi kanallar doğrulanmadan `ENROLLED` veya `READY` olmaz.
|
||||
>
|
||||
> - Dosya: `docs/27-OFFLINE-PROVISIONING.md`
|
||||
>
|
||||
> **Uygulama sözleşmesi:** Kurucu, paket setini **kendi kendine bulur** ve varsayılan olarak yerel depodan kurar; `--offline` bayrağı artık **gerekmez** (geriye uyumluluk için kabul edilir, yalnız yerel depoyu zorlar). Arama sırası: (1) `BF_OFFLINE_REPO` ortam değişkeni, (2) `<depo>/provisioning/offline-repo/built`, (3) `/opt/blueforce/offline-repo`; ilk eksiksiz aday kazanır. Yerel `file:` APT kaynağı dışında hiçbir kaynak kullanılmaz: uzak APT source, curl, wget, anahtar indirme veya `apt download` çağrılmaz. **İnternet kurulum için gerekmez.** İki farklı başarısızlık vardır: depo hiç yoksa kurulum Türkçe bir hata, aranan yollar ve `ÇIKIŞ NEDENİ: yerel paket deposu bulunamadı.` ile durur; depo bulunup da doğrulanamazsa (eksik `Packages`, `Packages.gz`, `packages.lock.tsv`, `SHA256SUMS`; checksum uyuşmazlığı; boş/bozuk kilit; eksik pin) `OFFLINE BLOCKED: <sebep>` ile durur. Her iki durumda da paket modüllerinden önce durulur, kurulum başlamaz ve sistemde hiçbir değişiklik yapılmaz. Paketler bu git deposunda taşınır ve **repo sorumlusu** tarafından `add-packages.sh` + `build-index.sh` ile bu depoya konur; kuran kişi hiçbir şey indirmez. Yalnız geliştirme/test için `--online` vardır ve **üretim cihazlarında kullanılmaz**. Grafik arayüz `python3-tk` paketine bağlıdır; bu paket offline depoda bilinçli olarak pinlidir (`manifests/base-packages.txt`).
|
||||
> **Uygulama sözleşmesi:** Kurucu, paket setini **kendi kendine bulur** ve varsayılan olarak yerel depodan kurar; `--offline` bayrağı artık **gerekmez** (geriye uyumluluk için kabul edilir, yalnız yerel depoyu zorlar). Arama sırası: (1) `BF_OFFLINE_REPO` ortam değişkeni, (2) `<depo>/provisioning/offline-repo/built`, (3) `/opt/blueforce/offline-repo`; ilk eksiksiz aday kazanır. Yerel `file:` APT kaynağı dışında hiçbir kaynak kullanılmaz: uzak APT source, curl, wget, anahtar indirme veya `apt download` çağrılmaz. **İnternet kurulum için gerekmez.** İki farklı başarısızlık vardır: depo hiç yoksa kurulum Türkçe bir hata ve `ÇIKIŞ NEDENİ: yerel paket deposu bulunamadı.` ile durur; depo bulunup da doğrulanamazsa (eksik `Packages`, `Packages.gz`, `packages.lock.tsv`, `SHA256SUMS`; checksum uyuşmazlığı; boş/bozuk kilit; eksik pin) `OFFLINE BLOCKED: <sebep>` ile durur. Her iki durumda da paket modüllerinden önce durulur, kurulum başlamaz ve sistemde hiçbir değişiklik yapılmaz. Paketler bu git deposunda taşınır ve **repo sorumlusu** tarafından `add-packages.sh` + `build-index.sh` ile bu depoya konur; kuran kişi hiçbir şey indirmez. Yalnız geliştirme/test için `--online` vardır ve **üretim cihazlarında kullanılmaz**.
|
||||
> - İlgili kararlar: `24-DECISION-LOG.md#K-16`, `#K-09`, `#K-11`, `#K-12`
|
||||
> - İlgili dokümanlar: `05-ONE-CLICK-INSTALLER.md` (kurucu), `33-OPERATOR-CONSOLE.md` (arayüz), `provisioning/offline-repo/README.md` (paket hazırlama)
|
||||
> - Durum: [ ] Taslak
|
||||
|
||||
---
|
||||
|
||||
## 1. Amaç
|
||||
|
||||
Saha interneti kesik veya güvenilmezken tekrarlanabilir, denetlenebilir ve secretsiz ilk kurulumu tanımlamak. Kuran kişi paket aramaz, indirmez, bayrak ezberlemez: paket seti depoyla birlikte gelir.
|
||||
Saha interneti kesik veya güvenilmezken tekrarlanabilir, denetlenebilir ve secretsiz ilk kurulumu tanımlamak.
|
||||
|
||||
## 2. Kapsam
|
||||
|
||||
- Kapsam içi: git checkout (paketler dahil) veya kurulmuş `/opt/blueforce/offline-repo`, offline APT bundle (`built/`), kurucunun yerel depoyu otomatik bulması, iki hata durumu, grafik arayüz üzerinden kurulum, `python3-tk` pini, durum damgası ve sonradan enrollment.
|
||||
- Kapsam dışı: merkezi peer atama ve token doğrulama (29), release imzalama (30), paket setinin nasıl üretildiği (repo sorumlusunun işi, `provisioning/offline-repo/README.md`).
|
||||
- Kapsam içi: seed USB veya git checkout, offline APT repository/snapshot, kurucunun yerel depoyu otomatik bulması, durum damgası ve sonradan enrollment.
|
||||
- Kapsam dışı: merkezi peer atama ve token doğrulama (29), release imzalama (30).
|
||||
|
||||
## 3. Kararlar
|
||||
|
||||
```text
|
||||
KARAR: Paket seti git deposunda taşınır ve cihaz grafik arayüzden (`sudo bf` → Kurulum → "Bu cihazı kur") internetsiz kurulur; paket deposu kurucu tarafından otomatik bulunur ve sonuç durumu yalnızca PROVISIONED_OFFLINE'dır.
|
||||
GEREKÇE: Paket indirme veya merkezi API'ye erişim yokken cihaz standarda getirilebilir; fakat merkezde doğrulanmamış kimlik ve kanallar READY iddiası yapamaz. Kuran kişinin indirme yapmaması ve bayrak hatırlamaması saha hatasını ortadan kaldırır: yerel depo varsayılan ve tek kaynaktır.
|
||||
KARAR: Offline kurulum, imzalı/sürümlü medya ya da git checkout ve ayrı offline APT kaynağıyla yapılır; paket seti kurucu tarafından otomatik bulunur ve sonuç durumu yalnızca PROVISIONED_OFFLINE'dır.
|
||||
GEREKÇE: Paket indirme veya merkezi API'ye erişim yokken cihaz standarda getirilebilir; fakat merkezde doğrulanmamış kimlik ve kanallar READY iddiası yapamaz. Operatörün hatırlaması gereken bayrak sayısı azaldıkça saha hatası azalır: yerel depo varsayılan kaynaktır.
|
||||
ALTERNATİF: İnternet gelene kadar kurulum yapmama — saha ziyareti ve bekleme maliyeti nedeniyle elendi. Kurulumu `--offline` bayrağına bağlamak — operatör bayrağı unuttuğunda kurulum durur; otomatik keşif seçildi, bayrak geriye uyumluluk için korundu.
|
||||
RİSK: Eski veya karışık paket snapshot'ı; manifest, checksum ve release kimliği ile azaltılır. Yanlış/eski depo bulunması; arama sırası ve her adayda eksiksizlik denetimi ile azaltılır. Grafik arayüzün `python3-tk` paketine bağımlılığı; paketin offline depoda pinlenmesi ve eksikliğinde `sudo bf --tui` yedeği ile azaltılır.
|
||||
MALİYET: Ücretsiz (depo boyutu git tarafında ~888 MB).
|
||||
RİSK: Eski veya karışık paket snapshot'ı; manifest, checksum ve release kimliği ile azaltılır. Yanlış/eski depo bulunması; arama sırası ve her adayda eksiksizlik denetimi ile azaltılır.
|
||||
MALİYET: Ücretsiz.
|
||||
LİSANS: APT — https://manpages.ubuntu.com/manpages/noble/en/man8/apt.8.html ; dpkg — https://manpages.ubuntu.com/manpages/noble/en/man1/dpkg.1.html ; Ubuntu offline kurulum ayrıntısı 26.04 için LAB doğrulamalıdır.
|
||||
```
|
||||
|
||||
## 4. Neden Bu Karar?
|
||||
|
||||
**Paketler artık ayrı bir medyada değil, bu git deposunda taşınır:** `provisioning/offline-repo/packages/` altında 1321 `.deb` (~888 MB) durur ve `.gitattributes` ile **Git LFS** üzerinden takip edilir (`*.deb filter=lfs ...`). Bu yüzden sahada "hangi paket nereden geldi?" sorusu ne internete ne de dış medyaya bağlıdır; aynı soru `packages.lock.tsv` ve `repo-manifest.yaml` ile yanıtlanır. Kuran kişi paket aramaz ve **indirmez**; klonladığı depo seti zaten taşır.
|
||||
|
||||
Durum makinesi, "kuruldu" ile "merkezce güvenildi" arasındaki farkı görünür yapar: offline kurulum yalnız `PROVISIONED_OFFLINE` üretir.
|
||||
Offline medya ve git deposu, işletim sistemi ve zorunlu paketleri taşır; merkezi sırları taşımamalıdır. Durum makinesi, "kuruldu" ile "merkezce güvenildi" arasındaki farkı görünür yapar. Paket setini **repo sorumlusu** hazırlayıp sürümlediği için sahada "hangi paket nereden geldi?" sorusu `packages.lock.tsv` ve `repo-manifest.yaml` ile yanıtlanır; kuran kişi paket aramaz ve indirmez.
|
||||
|
||||
## 5. Alternatifler
|
||||
|
||||
| Alternatif | Artı | Eksi | Sonuç |
|
||||
|---|---|---|---|
|
||||
| Sürümlü offline APT bundle + repoda taşınan paketler | Tekrarlanabilir, indirme yok, medya lojistiği yok | Git deposu ~888 MB büyür (LFS) | **Seçildi** |
|
||||
| Ayrı fiziksel seed USB medyası | Depo küçük kalır | Medya zimmeti/sürüm takibi, kaybolma riski | Yedek/geri dönüş yolu |
|
||||
| Sürümlü offline APT repo | Tekrarlanabilir | Medya yönetimi | **Seçildi** |
|
||||
| Rastgele `.deb` dosyaları | İlk anda kolay | Bağımlılık/sürüm belirsiz | Elendi |
|
||||
| İnternet bekleme | Basit | Saha blokajı | Elendi |
|
||||
| Yerel depoyu operatörün `--offline` bayrağıyla göstermesi | Basit | Bayrak unutulunca kurulum durur, saha hatası üretir | Elendi (bayrak geriye uyumluluk için korundu) |
|
||||
|
||||
## 6. Avantajlar
|
||||
|
||||
- Bağlantısız sahada standarda yakın kurulum; **kuran kişi hiçbir indirme yapmaz** ve bayrak ezberlemez.
|
||||
- Paket manifesti ve kilit dosyası ile hangi sürümün yüklendiği kanıtlanır.
|
||||
- Nesil farkı yoktur: repo sorumlusu paketleri bir kez commit eder, 700 cihaz aynı setten kurulur.
|
||||
- Kurulum akışı grafik arayüzde tek düğmedir; terminal bilgisi gerekmez.
|
||||
- Bağlantısız sahada standarda yakın kurulum.
|
||||
- Paket manifesti ile hangi sürümün yüklendiği kanıtlanır.
|
||||
- Kurulum yapan kişi **hiçbir indirme yapmaz** ve bayrak ezberlemez: paketler zaten deponun içindedir, kurucu depoyu kendisi bulur.
|
||||
|
||||
## 7. Dezavantajlar
|
||||
|
||||
- Git deposu paket setiyle birlikte büyür (LFS clone/pull maliyeti); derin clone sahada zaman alabilir.
|
||||
- Medya sürümü ve paket snapshot'ı düzenli yenilenmelidir.
|
||||
- Offline cihaz merkezi izleme ve erişim kanalları doğrulanana kadar operasyonel olarak hazır değildir.
|
||||
- Paket snapshot'ı yenilenmediği sürece güvenlik güncellemeleri geride kalır (onaysız update zaten yasak, K-11).
|
||||
|
||||
## 8. Riskler
|
||||
|
||||
| Risk | Olasılık | Etki | Azaltma |
|
||||
|---|---|---|---|
|
||||
| Eski güvenlik paketi | Orta | Orta | Süre sonu olan release medyası/repo sürümü, hızlı enrollment kuyruğu |
|
||||
| Secret repoda kalır | Düşük | Yüksek | Secret taraması (test), token yalnız bir kez ve cihazda girilir |
|
||||
| Eski güvenlik paketi | Orta | Orta | Süre sonu olan release medyası, hızlı enrollment kuyruğu |
|
||||
| Secret USB'ye yazılır | Düşük | Yüksek | Secret taraması; token yalnız bir kez ve cihazda girilir |
|
||||
| Yarım paket işlemi | Orta | Orta | `dpkg --configure -a`, idempotent kurucu |
|
||||
| Kurucu yanlış/eski depoyu bulur | Düşük | Orta | Arama sırası sabittir; aday eksiksiz değilse kullanılmaz, `BF_OFFLINE_REPO` ile açıkça yönlendirilebilir |
|
||||
| Paketler var ama indeks (`built/`) yok | Orta | Yüksek | Kurucu fail-closed durur ("yerel paket deposu yok"); repo sorumlusu `build-index.sh` koşup `built/` dizinini commit eder |
|
||||
| Grafik arayüz açılamıyor | Orta | Düşük | `python3-tk` offline depoda pinli; ekransız ortamda `sudo bf --tui` |
|
||||
| Kurucu yanlış/eski depoyu bulur | Düşük | Orta | Arama sırası sabittir; aday eksiksiz değilse kullanılmaz, en son `BF_OFFLINE_REPO` ile açıkça yönlendirilebilir |
|
||||
|
||||
## 9. Uygulama Planı
|
||||
|
||||
1. Medya/repo manifesti: Field OS release, ISO checksum, offline APT snapshot kimliği, kurucu commit'i.
|
||||
2. Paket setini **repo sorumlusu** hazırlar: `.deb` dosyalarını `add-packages.sh` ile `provisioning/offline-repo/packages/` altına koyar (Git LFS), pinleri `manifests/*.txt` içinde `package=version` olarak doldurur, `build-index.sh` ile `provisioning/offline-repo/built/` indeksini (`Packages`, `Packages.gz`, `packages.lock.tsv`, `SHA256SUMS`, `pool/`) üretir. Kuran kişi yalnız git tarafını çeker.
|
||||
1. Medya manifesti: Field OS release, ISO checksum, seed checksum, offline APT snapshot kimliği, kurucu commit'i.
|
||||
2. Paket setini **repo sorumlusu** hazırlar: `.deb` dosyalarını `add-packages.sh` ile depoya koyar, `build-index.sh` ile `provisioning/offline-repo/built` indeksini üretir, `packages.lock.tsv` / `SHA256SUMS` / `repo-manifest.yaml` ile birlikte commit eder. Kuran kişi yalnız git tarafını çeker.
|
||||
3. Kurulumda yalnız genel paketler kullanılır; kurucu yerel depoyu **otomatik bulur** ve `--offline` gerekmez.
|
||||
4. Kurucu yerel durum dosyasına `PROVISIONED_OFFLINE` yazar; `READY` yazması yasaktır.
|
||||
5. İnternet geldiğinde 29'daki tek-kullanımlık token ile enrollment başlatılır; sonra merkezi kanallar test edilir.
|
||||
|
||||
### Kuran kişinin akışı (grafik arayüz — ana yol)
|
||||
|
||||
1. Depoyu getir: `git clone <repo>` (paketler Git LFS ile gelir) — veya repo sorumlusunun bıraktığı kopyada `/opt/blueforce/offline-repo` hazırdır.
|
||||
2. `sudo bf` — pencere açılır: **Blueforce Field OS — Yönetim**.
|
||||
3. Üst çubuk **Hedef > Bayi no (8 hane)** alanına numarayı yaz (örn. `12010193`).
|
||||
4. **Kurulum** sekmesi → **`Bu cihazı kur`** (hiçbir şey yazmayan ön kontrol için: `Kurulum ön kontrolü (--check)`).
|
||||
5. Komut ekranda gösterilir, onay istenir; onaylandıktan sonra kurulum çalışır. `--offline` işaretlemek **zorunlu değildir** (varsayılan kaynak zaten yerel depodur).
|
||||
6. Sonuç: `PROVISIONED_OFFLINE`. Arayüzdeki **Kurulum modül durumu** ve `bf-status` ile doğrulanır.
|
||||
Kuran kişinin komutu (bayrak yok, tek zorunlu bilgi bayi numarası):
|
||||
|
||||
```bash
|
||||
# Ana yol (grafik arayüz)
|
||||
# Konsoldan (önerilen): Python operatör konsolu; bash yedek yolu sudo bf-menu
|
||||
sudo bf
|
||||
# → Hedef: Bayi no (8 hane) → Kurulum sekmesi → "Bu cihazı kur"
|
||||
|
||||
# Yedek yol (grafik ekran yoksa veya python3-tk yoksa): aynı uygulamanın terminal arayüzü
|
||||
sudo bf --tui
|
||||
|
||||
# Doğrudan kurucu ile (otomasyon / teşhis)
|
||||
# Doğrudan kurucu ile
|
||||
sudo ./scripts/install/blueforce-install.sh --dealer-id 12010193
|
||||
|
||||
# Bilinçli olarak başka bir depo dizinini göstermek (nadir, repo sorumlusu isterse)
|
||||
|
|
@ -104,10 +85,6 @@ BF_OFFLINE_REPO=/mnt/blueforce-repo/built \
|
|||
sudo ./scripts/install/blueforce-install.sh --dealer-id 12010193
|
||||
```
|
||||
|
||||
### Depo keşfi ve iki hata durumu
|
||||
|
||||
Sıra (ilk eksiksiz aday kazanır): `BF_OFFLINE_REPO` → `<repo>/provisioning/offline-repo/built` → `/opt/blueforce/offline-repo`. Bir aday "eksiksiz" sayılmak için `Packages`, `Packages.gz`, `packages.lock.tsv` ve `SHA256SUMS` dosyalarının hepsini içermelidir; yalnız `packages/` (ham `.deb` havuzu) yeterli **değildir** — indeksin `build-index.sh` ile üretilmiş olması gerekir.
|
||||
|
||||
Depo bulunduğunda ekranda şu duyuru çıkar:
|
||||
|
||||
```text
|
||||
|
|
@ -121,16 +98,7 @@ Depo hiçbir yerde yoksa kurulum başlamadan durur:
|
|||
|
||||
```text
|
||||
HATA: Yerel paket deposu yok. Repo sorumlusuna başvurun: provisioning/offline-repo/README.md
|
||||
|
||||
Aranan yerler:
|
||||
- depodaki hazır paket seti — yok: <repo>/provisioning/offline-repo/built
|
||||
- cihazdaki kurulu paket deposu — yok: /opt/blueforce/offline-repo
|
||||
|
||||
Ne yapmalı:
|
||||
1) Paket setini git ile tam olarak getirin ... ya da /opt/blueforce/offline-repo altına koyun.
|
||||
2) Kurulumu yeniden çalıştırın.
|
||||
|
||||
Kuruluma hiç başlanmadı; sistemde hiçbir değişiklik yapılmadı.
|
||||
...
|
||||
ÇIKIŞ NEDENİ: yerel paket deposu bulunamadı.
|
||||
```
|
||||
|
||||
|
|
@ -146,22 +114,15 @@ OFFLINE BLOCKED: <sebep>
|
|||
|
||||
`--online` yalnız geliştirme/test makinesi içindir; paketleri internetten çeker ve üretim cihazlarında kullanılmaz.
|
||||
|
||||
### `python3-tk` neden offline depoda pinli?
|
||||
|
||||
Grafik operatör uygulaması Tkinter ile yazılmıştır ve tkinter Ubuntu'da **ayrı bir pakettir** (`python3-tk`); minimal Ubuntu Server kurulumunda Python vardır ama tkinter yoktur. İnternetsiz sahada `apt install python3-tk` **çalışmaz**, bu yüzden paket ve bağımlılık kümesi (`python3-tk`, `python3.14-tk`, `libtk8.6`) `provisioning/offline-repo/manifests/base-packages.txt` içinde pinlidir ve depodan gelir. Kurulum sonu kapısı `scripts/install/installer/modules/18-final-check.sh` tkinter'ı denetler; eksikse **WARN** yazar ve kurulumu düşürmez (cihaz yine kurulur, operatör terminal konsoluna `sudo bf --tui` ile devam eder).
|
||||
|
||||
## 10. Test Planı
|
||||
|
||||
| Test | Beklenen sonuç | Ortam |
|
||||
|---|---|---|
|
||||
| İnternetsiz kurulum | Paketler manifestten kurulur, dış indirme yok | LAB(2) air-gapped |
|
||||
| Depo yolu verilmeden kurulum | Kurucu depoyu otomatik bulur (`repo/built`), duyuru satırını yazar | LAB(2) |
|
||||
| Grafik arayüzden kurulum | `sudo bf` → Kurulum → "Bu cihazı kur" ile `PROVISIONED_OFFLINE` | LAB(2) masaüstü oturumu |
|
||||
| `BF_OFFLINE_REPO` ile başka dizin | Verilen dizin kullanılır; geçersizse durur | LAB(2) |
|
||||
| Depo hiç yok | Türkçe hata + aranan yollar + `ÇIKIŞ NEDENİ: yerel paket deposu bulunamadı.`, exit 1, sistem değişmez | LAB(2) |
|
||||
| Depo hiç yok | Türkçe hata + `ÇIKIŞ NEDENİ: yerel paket deposu bulunamadı.`, exit 1, sistem değişmez | LAB(2) |
|
||||
| Depo var ama bozuk (checksum/pin) | `OFFLINE BLOCKED: <sebep>` + Türkçe çıkış nedeni, exit 1, sistem değişmez | LAB(2) |
|
||||
| Yalnız `packages/` var, `built/` yok | Depo "yok" sayılır, kurulum başlamaz (fail-closed) | LAB(2) |
|
||||
| `python3-tk` eksik imaj | `sudo bf` Türkçe hata + ipucu, exit 3; `18-final-check` WARN yazar, kurulum düşmez | LAB(2) |
|
||||
| DNS/WAN kesik | Kurucu dış indirme istemez; `01-precheck` ağı yalnız bilgi olarak yazar, `05-network` DNS zorunlu tutmaz | LAB(2) |
|
||||
| `--online` üretimde denenmez | Yalnız geliştirme/test; kurucu uyarı yazar | LAB(2) |
|
||||
| `bf-status` | `PROVISIONED_OFFLINE`; READY değil | LAB(2) |
|
||||
|
|
@ -170,29 +131,26 @@ Grafik operatör uygulaması Tkinter ile yazılmıştır ve tkinter Ubuntu'da **
|
|||
## 11. Rollback
|
||||
|
||||
1. Paket işlemi bozuksa aynı onaylı snapshot ile `dpkg --configure -a` ve kurucu yeniden çalıştırılır.
|
||||
2. Yanlış repo sürümü geri çekilir; önceki onaylı manifestle yeniden kurulur.
|
||||
2. Yanlış medya sürümü geri çekilir; önceki onaylı medya manifestiyle yeniden kurulur.
|
||||
3. Yerel depo bozuksa sahada onarılmaz: repo sorumlusu depoyu yeniden üretip commit eder (`add-packages.sh` + `build-index.sh`), kurulum yapan kişi güncel git tarafını çekip komutu tekrarlar.
|
||||
4. Kimlik/token hatasında cihaz resetlenmez; 29'daki token iptal/yenileme prosedürü uygulanır.
|
||||
5. Arayüz sorunuysa (ekran/tkinter) rollback gerekmez: `sudo bf --tui` ile aynı akış yürütülür.
|
||||
|
||||
## 12. Kontrol Listesi
|
||||
|
||||
- [ ] Paket seti repoda: `provisioning/offline-repo/packages/` (1321 `.deb`, Git LFS ile takip ediliyor).
|
||||
- [ ] Bundle indeksi repoda: `provisioning/offline-repo/built/` (`Packages`, `Packages.gz`, `packages.lock.tsv`, `SHA256SUMS`, `pool/`).
|
||||
- [ ] Offline medya/git manifesti ve checksum'ları var.
|
||||
- [ ] Paket seti repoda: `provisioning/offline-repo/built` (`Packages`, `Packages.gz`, `packages.lock.tsv`, `SHA256SUMS`, `pool/`).
|
||||
- [ ] `repo-manifest.yaml` güncel; pin listesi ile paket havuzu uyuşuyor.
|
||||
- [ ] Depoda/repoda cihaz kimliği, private key veya kalıcı token yok.
|
||||
- [ ] `python3-tk` ve bağımlılıkları `manifests/base-packages.txt` içinde pinli; `18-final-check` tkinter'ı denetliyor.
|
||||
- [ ] Medyada/depoda cihaz kimliği, private key veya kalıcı token yok.
|
||||
- [ ] Kuran kişinin komutu `--offline` bayrağı istemiyor; depo otomatik bulunuyor.
|
||||
- [ ] Grafik arayüz akışı (bayi no → Kurulum → "Bu cihazı kur") yazılı ve ekransız ortam için `sudo bf --tui` belgeli.
|
||||
- [ ] İnternet kapalıyken kurulum tamamlanıyor; dış indirme çağrısı yok.
|
||||
- [ ] `PROVISIONED_OFFLINE` görünür ve READY kapısı kapalı.
|
||||
- [ ] Sonradan enrollment sahibi/kuyruğu kayıtlı.
|
||||
|
||||
## 13. Açık Sorular
|
||||
|
||||
- [ ] Offline paket seti yenileme sıklığı ve Git LFS bant genişliği/kotaysa sahaya taşıma yöntemi — sahibi: release yöneticisi.
|
||||
- [ ] Paketlerin sahaya taşınmasında git clone mu, hazır `/opt/blueforce/offline-repo` kopyası mı birincil — sahibi: saha operasyonu + 05 yazarı.
|
||||
- [ ] `--online` geliştirme yolunun hangi ortamlarda serbest olduğu — sahibi: yönetim + 26/33 yazarları.
|
||||
- [ ] Offline APT snapshot yenileme sıklığı — sahibi: release yöneticisi.
|
||||
- [ ] Medyanın fiziksel zimmet ve imha süreci — sahibi: saha operasyonu.
|
||||
- [ ] Git checkout ile ISO/medya yolundan hangisinin birincil olduğu ve `--online` geliştirme yolunun hangi ortamlarda serbest olduğu — sahibi: yönetim + 26/33 yazarları.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -200,9 +158,8 @@ Grafik operatör uygulaması Tkinter ile yazılmıştır ve tkinter Ubuntu'da **
|
|||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
M["git checkout (paketler LFS ile)<br/>veya /opt/blueforce/offline-repo"] --> G["sudo bf → Kurulum → 'Bu cihazı kur'"]
|
||||
G --> D{"Kurucu yerel depoyu arar<br/>BF_OFFLINE_REPO → repo/built → /opt/blueforce/offline-repo"}
|
||||
D -->|"hiçbiri yok / eksik"| X["HATA: Yerel paket deposu yok<br/>aranan yollar + ÇIKIŞ NEDENİ · exit 1<br/>sistem değişmez"]
|
||||
M["ISO/seed veya git checkout<br/>+ repodaki offline APT"] --> D{"Kurucu yerel depoyu arar<br/>BF_OFFLINE_REPO → repo/built → /opt/blueforce/offline-repo"}
|
||||
D -->|"hiçbiri yok / eksik"| X["HATA: Yerel paket deposu yok<br/>ÇIKIŞ NEDENİ: bulunamadı · exit 1<br/>sistem değişmez"]
|
||||
D -->|"eksiksiz aday bulundu"| V{"Doğrulama katmanı:<br/>dosya listesi, SHA256SUMS, kilit, pin ↔ pool"}
|
||||
V -->|"başarısız"| B["OFFLINE BLOCKED: sebep<br/>ÇIKIŞ NEDENİ: doğrulanamadı · exit 1"]
|
||||
V -->|"geçti"| P["PROVISIONED_OFFLINE"]
|
||||
|
|
|
|||
|
|
@ -1,162 +1,95 @@
|
|||
# 33 — Operatör Arayüzü Rehberi (`bf`)
|
||||
# 33 — Operatör Konsolu Rehberi (`bf-menu`)
|
||||
|
||||
> Kısa özet: Bu rehber, Linux/DevOps'a yeni başlayan bir operatörün Blueforce cihazını **git deposundan** kurmasını ve tek giriş noktası olan `sudo bf` **grafik operatör uygulaması** ile cihazı işletmesini adım adım anlatır. Kurulum, filo işlemleri, merkez hazırlığı, araçlar ve cihaz bilgisi işlerinin tamamı bu pencereden açılır; komut ezberlemek gerekmez.
|
||||
> Kısa özet: Bu rehber, Linux/DevOps'a yeni başlayan bir operatörün Blueforce cihazını **git deposundan** kurmasını ve tek giriş noktası olan `sudo bf-menu` **kategori menüsü** ile cihazı işletmesini adım adım anlatır. Kurulum, filo işlemleri, merkez hazırlığı, araçlar ve cihaz bilgisi ekranlarının tamamı bu menüden açılır; komut ezberlemek gerekmez.
|
||||
|
||||
- Dosya: `docs/33-OPERATOR-CONSOLE.md`
|
||||
- İlgili kararlar: `24-DECISION-LOG.md#K-09` (golden image + kurucu), `#K-12` (kimlik formatı `^[0-9]{8}$`), `#K-13` (SSH anahtar zorunlu), `#K-11` (onaysız update yasağı), `#K-21` (durum modeli), `#K-22` (RDP her zaman hazır / `bf-gui-*` yalnız yerel GUI)
|
||||
- Uygulama: Python paketi `bfos` (depo kökü) — `bfos/ui_gui.py` (grafik arayüz, tkinter), `bfos/tui.py` + `bfos/cli.py` (terminal konsolu), `bfos/operations.py` (iş mantığı + işlem kataloğu), `bfos/runner.py` (çalıştırma + denetim kaydı), `bfos/config.py` (Türkçe metinler)
|
||||
- Giriş noktası: `admin/bf` (sarmalayıcı) → `sudo bf` ve `sudo bf --tui`. Kurucu: `admin/bf-bootstrap.sh`
|
||||
- Yedek yol: `admin/bf-menu` + `admin/lib/*` (eski bash konsolu) — ana yol değildir; yalnız Python'suz cihazlar ve olağanüstü durumlar için korunur
|
||||
- Durum: [ ] Taslak — pencere yerleşimi ve örnek satırlar LAB'da alınan gerçek koşuyla güncellenir
|
||||
- Uygulama: `admin/bf-menu` (+ `admin/lib/tui.sh`, `admin/lib/targets.sh`), `admin/bf-bootstrap.sh`, `admin/bf-creds`
|
||||
- Durum: [ ] Taslak — ekran çıktıları **örnektir (taklit)** ve LAB'da alınan gerçek çıktıyla güncellenir
|
||||
|
||||
> **Dürüstlük notu (bu reponun kuralı):** Aşağıdaki pencere ve çıktı örnekleri, tasarımı anlatmak için yazılmıştır. Gösterilen metinler uygulamanın kaynağından (`bfos/ui_gui.py`, `bfos/config.py`, `bfos/runner.py`) alınmış **gerçek satır biçimleridir**; ancak pencere yerleşimi tema, ekran çözünürlüğü ve envanter içeriğine göre birebir farklı görünür. Kurulum betiğinin kendi çıktısı (`[installer] ...` satırları) LAB koşusunda bu dosyaya işlenir (§10, §13).
|
||||
> **Dürüstlük notu (bu reponun kuralı):** Aşağıdaki menü ekranları ve çıktılar, tasarımı anlatmak için yazılmış **örnek ekranlardır**; terminal genişliğine, renklerin kapalı olmasına ve envanter içeriğine göre birebir farklı görünebilir. Gerçek çıktılar ilk LAB koşusunda bu dosyaya işlenir (§10, §13).
|
||||
|
||||
---
|
||||
|
||||
## 1. Amaç
|
||||
|
||||
**Bu araç nedir?** `bf`, cihaza `sudo bf` yazınca açılan **grafik operatör uygulamasıdır**. Varsayılan olarak **basit mod** gelir: ekranda üç büyük düğme vardır — `Kur`, `Durum`, `Çıkış`. Üst çubuktaki `Detaylı mod` düğmesiyle **5 kategori sekmesi** açılır: Kurulum, Cihaz işlemleri, Merkez hazırlığı, Araçlar, Cihaz bilgisi. Listeden bir işlem seçip `Komutu göster ve çalıştır` düğmesine basarsın; uygulama senin adına doğru komutu üretir, çalıştırmadan **önce gösterip onay ister** ve ne yaptığını Türkçe satırlarla akıtır.
|
||||
**Bu araç nedir?** `bf-menu`, cihaza `sudo bf-menu` yazınca açılan, numaralarla gezilen bir **operatör konsoludur**. Ekranda 5 kategori çıkar (Kurulum, Cihaz işlemleri, Merkez hazırlığı, Araçlar, Cihaz bilgisi); bir numara yazıp Enter'a basarsın, konsol senin adına doğru komutu çalıştırır ve ne yaptığını Türkçe/İngilizce satırlarla gösterir.
|
||||
|
||||
**Neyi kolaylaştırır?** Normalde cihazı kurmak, durumunu okumak, teşhis paketi almak veya bir filo işlemi başlatmak için onlarca komutu ve doğru sırasını bilmek gerekir. `bf` bunları sekmeler ve arama yapılabilir listeler altında toplar, her komutu **çalıştırmadan önce** gösterir, tehlikeli işlemlerde ikinci kez sorar, `production` dalgası ve sürüm kapısı için ayrı onay ister ve her işlemi bir denetim kaydına (`/var/log/blueforce-console.log`, mod `600`) yazar. Kısacası: ezberleyeceğin tek şey `sudo bf` komutudur.
|
||||
**Neyi kolaylaştırır?** Normalde cihazı kurmak, durumunu okumak, teşhis paketi almak veya bir filo işlemi başlatmak için onlarca komutu ve doğru sırasını bilmek gerekir. `bf-menu` bunları numaralı başlıklar altında toplar, **çalıştırmadan önce komutu ekranda gösterip onay ister**, tehlikeli işlemlerde iki kez sorar ve her işlemi bir denetim log'una (`/var/log/blueforce-console.log`, mod `600`) yazar. Kısacası: ezberleyeceğin tek şey `sudo bf-menu` komutudur.
|
||||
|
||||
## 2. Kapsam
|
||||
|
||||
- Kapsam içi: Ubuntu'da ilk kurulum (git'ten indir + bootstrap), basit mod ve 5 kategori sekmesi, üst çubuktan hedef seçimi (bayi no / dalga / tüm filo), uçtan uca örnek seans, yetki modeli (`sudo bf` = tam yetki), şifre dosyası (`bf-creds`) davranışı, grafik arayüz açılamadığında ne olacağı, en sık hatalar ve güvenlik kuralları.
|
||||
- Kapsam dışı: ISO/firstboot/offline provisioning yolu (26, 27 — artık **ikincil/opsiyonel**), merkez sunucularının kurulumu (07, 09 — arayüz yalnız **hazırlar ve denetler**, kurmaz), update onay zincirinin merkez tarafı (10, 21), rol bazlı eğitim müfredatı (31).
|
||||
- Kapsam içi: Ubuntu'da ilk kurulum (git'ten indir + bootstrap), ana menü ve 5 kategori, tek cihaz/grup/tüm filo hedef seçimi, uçtan uca örnek seans, şifre dosyası (`bf-creds`) davranışı, en sık 5 hata ve güvenlik kuralları.
|
||||
- Kapsam dışı: ISO/firstboot/offline provisioning yolu (26, 27 — artık **ikincil/opsiyonel**), merkez sunucularının kurulumu (07, 09 — konsol yalnız **hazırlar ve denetler**, kurmaz), update onay zincirinin merkez tarafı (10, 21), rol bazlı eğitim müfredatı (31).
|
||||
|
||||
## 3. Kararlar
|
||||
|
||||
```text
|
||||
KARAR: Cihaz ve filo işlemlerinin tek operatör giriş noktası `sudo bf` grafik uygulamasıdır
|
||||
(`bfos/ui_gui.py`, tkinter). Operatör komut ezberlemez; basit modda üç düğmeden,
|
||||
detaylı modda kategori sekmesinden seçer.
|
||||
GEREKÇE: Operatör profili Linux/DevOps'a yeni başlayan kişidir; serbest komut yazımı 700 cihazda
|
||||
yazım hatasını filo arızasına çevirir (K-11 blast-radius). Arayüz her komutu
|
||||
çalıştırmadan önce gösterir ve onay ister; dalga kapılı playbook'lara bayrak sessizce
|
||||
geçirilmez, operatör kapıyı ayrıca onaylar.
|
||||
ALTERNATİF: Numara yazılan terminal menüsü (`sudo bf --tui`, aynı iş mantığı) — grafik ekran
|
||||
yoksa (SSH/başsız oturum) yedek yol olarak korunur. Eski bash konsolu (`admin/bf-menu`)
|
||||
— Python'suz cihaz için son çare olarak durur, ana yol değildir.
|
||||
Yalnız merkez Semaphore UI — saha cihazında çevrimdışıyken erişilemez; merkez tarafı
|
||||
için korunur (09).
|
||||
RİSK: Arayüzün katalog tablosu, altındaki playbook'tan ayrışır ve yanlış kapıyla çalıştırır;
|
||||
azaltma: komut üretimi playbook kapsamını (simple/wave/release) playbook dosyasının
|
||||
kendisinden okuyup karşılaştırır, uyuşmazlıkta **çalıştırmayı reddeder**
|
||||
(`bfos/operations.py` + `bfos/ui_gui.py` → kapsam karşılaştırması; yıkıcı işlemler için
|
||||
ayrıca katalog playbook'la senkron doğrulanır).
|
||||
KARAR: Cihaz ve filo işlemlerinin tek operatör giriş noktası `sudo bf-menu` kategori menüsüdür; operatör komut ezberlemez, numaralı kategoriden seçer.
|
||||
GEREKÇE: Operatör profili Linux/DevOps'a yeni başlayan kişidir; serbest komut yazımı 700 cihazda yazım hatasını filo arızasına çevirir (K-11 blast-radius). Konsol her komutu çalıştırmadan önce gösterir ve onay ister; dalga kapılı playbook'lara bayrak sessizce geçirilmez, operatör kapıyı ayrıca onaylar.
|
||||
ALTERNATİF: Operatörün dokümandan komut kopyalaması — sıra atlama ve yanlış hedef seçme riski yüksek; elendi. Yalnız merkez Semaphore UI — saha cihazında çevrimdışıyken erişilemez; merkez tarafı için korunur (09).
|
||||
RİSK: Konsolun tablosu, altındaki playbook'tan ayrışır ve yanlış kapıyla çalıştırır; azaltma: konsol her playbook'un kapsamını (simple/wave/release) playbook'un kendisinden okuyup karşılaştırır, uyuşmazlıkta **çalıştırmayı reddeder** (`admin/bf-menu` → `bf_playbook_check`).
|
||||
MALİYET: Ücretsiz.
|
||||
LİSANS: Yok (kurum içi operatör aracı).
|
||||
```
|
||||
|
||||
```text
|
||||
KARAR: Kurulum git deposundan yapılır: depo klonlanır ve `sudo admin/bf-bootstrap.sh`
|
||||
(veya `curl -fsSL <repo>/admin/bf-bootstrap.sh | sudo bash`) çalıştırılır. Kurulum
|
||||
paketleri DEPONUN İÇİNDEDİR (`provisioning/offline-repo/packages/`, 1321 .deb, Git LFS):
|
||||
kurulan cihaz HİÇBİR ŞEY İNDİRMEZ, kurulum için internet gerekmez. ISO/firstboot yolu
|
||||
(26, 27) silinmez, ikincil/opsiyonel yol olarak korunur.
|
||||
GEREKÇE: Dağıtım imajı/ISO üretimi bu fazda yapılmayacaktır; en hızlı doğrulanabilir yol, sürümü
|
||||
Git geçmişiyle izlenebilen tek bir bootstrap scriptidir. Bootstrap repoyu
|
||||
`/opt/blueforce-linux` (veya bulunduğu checkout) altına alır, ön koşulları kurar,
|
||||
`bf-*` araçlarını ve grafik arayüz girişini (`/usr/local/bin/bf`) `/usr/local/bin`'e
|
||||
bağlar; cihaz kimliği (bayi no) hiçbir zaman bir imaja gömülmez (K-09/K-12).
|
||||
İnternet yalnız `git clone` adımında gerekir; saha cihazı kurulduktan sonra çevrimdışı
|
||||
çalışır.
|
||||
ALTERNATİF: Tek USB Field OS ISO (K-20) — üretim/doğrulama maliyeti yüksek olduğu için bu fazda
|
||||
birincil yol değil; yedek olarak korunur. USB'ye elle kopyalama — sürüm izi ve
|
||||
güncellenebilirlik yok; elendi.
|
||||
RİSK: `curl | bash` deseni kötüye kullanıma açıktır; azaltma: script yalnız resmi depo
|
||||
adresinden çalıştırılır, `git clone` ile içeriği önce incelenebilir, secret yazmaz,
|
||||
`git reset`/`stash` yapmaz ve yerel değişiklikleri asla silmez.
|
||||
KARAR: Kurulum git deposundan yapılır: depo klonlanır ve `sudo admin/bf-bootstrap.sh` (veya `curl -fsSL <repo>/admin/bf-bootstrap.sh | sudo bash`) çalıştırılır. ISO/firstboot yolu (26, 27) silinmez, ikincil/opsiyonel yol olarak korunur.
|
||||
GEREKÇE: Dağıtım imajı/ISO üretimi bu fazda yapılmayacaktır; en hızlı doğrulanabilir yol, sürümü Git geçmişiyle izlenebilen tek bir bootstrap scriptidir. Bootstrap repoyu `/opt/blueforce-linux` (veya bulunduğu checkout) altına alır, ön koşulları (git, curl, ansible-core) kurar ve `bf-*` araçlarını `/usr/local/bin`'e bağlar; cihaz kimliği (bayi no) hiçbir zaman bir imaja gömülmez (K-09/K-12).
|
||||
ALTERNATİF: Tek USB Field OS ISO (K-20) — üretim/doğrulama maliyeti yüksek olduğu için bu fazda birincil yol değil; yedek olarak korunur. USB'ye elle kopyalama — sürüm izi ve güncellenebilirlik yok; elendi.
|
||||
RİSK: `curl | bash` deseni kötüye kullanıma açıktır; azaltma: script yalnız resmi depo adresinden çalıştırılır, `git clone` ile içeriği önce incelenebilir, secret yazmaz, `git reset`/`stash` yapmaz ve yerel değişiklikleri asla silmez.
|
||||
MALİYET: Ücretsiz.
|
||||
LİSANS: Yok (kurum içi script).
|
||||
```
|
||||
|
||||
```text
|
||||
KARAR: Grafik arayüz varsayılandır; açılamıyorsa uygulama SUSMAZ: Türkçe hata verir ve
|
||||
`sudo bf --tui` yolunu önerir. Grafik arayüz için gereken `python3-tk` paketi çevrimdışı
|
||||
depoda pinlidir (`provisioning/offline-repo/manifests/base-packages.txt`) ve kurulum
|
||||
sonu kapısı `scripts/install/installer/modules/18-final-check.sh` tkinter'ı ayrıca
|
||||
denetler; eksikse kurulum durdurulmaz, WARN yazıp terminal konsolunu işaret eder.
|
||||
GEREKÇE: Minimal imajlarda `python3` vardır ama pencere araç takımı yoktur; operatör ne arayüz
|
||||
ne de başka bir yol bulamazsa elinde hiçbir giriş noktası kalmaz ve cihazda internet
|
||||
olmadığı için bu durumu düzeltemez. Paketin depoda pinli olması bu riski kurulum
|
||||
anında kapatır; kapı ayrıca görünür bir uyarı bırakır.
|
||||
ALTERNATİF: tkinter'ı kurulum dışı bırakmak — sahada tek giriş noktası terminale düşerdi; elendi.
|
||||
tkinter yokluğunda kurulumu durdurmak — çalışan bir terminal konsolu varken cihazı
|
||||
kurulmamış bırakırdı; elendi (uyarı verilir, kurulum sürer).
|
||||
RİSK: Çevrimdışı depo güncellenmezse pin eskir; azaltma: paket seti Git LFS ile sürümlenir ve
|
||||
depo bütünlüğü kurulum öncesi doğrulanır (offline depo denetimi).
|
||||
MALİYET: Ücretsiz.
|
||||
LİSANS: Yok.
|
||||
```
|
||||
|
||||
```text
|
||||
KARAR: Şifre/kimlik bilgisi üretimi OPSİYONELDİR ve VARSAYILAN OLARAK KAPALIDIR; yalnız
|
||||
`bf-creds --generate` açıkça istendiğinde üretilir ve parola hiçbir zaman
|
||||
ekrana/loga/komut satırına yazılmaz.
|
||||
GEREKÇE: SSH zaten anahtar zorunludur (parola girişi kapalı, `blueforce` hesabı kilitli — K-13);
|
||||
kullanılmayan bir parola üretmek sızma yüzeyini büyütür. Varsayılan kapalı olması
|
||||
secret'ın git'e/medyaya/support bundle'a kaçmasını da baştan engeller.
|
||||
ALTERNATİF: Kurulumda otomatik parola üretimi — hiçbir kanal bu parolayı kullanmadığı için
|
||||
gereksiz secret üretir; elendi. Parolayı repoya/ISO'ya gömmek — secret yasağına aykırı;
|
||||
yasak.
|
||||
RİSK: Kayıt dosyası yanlış yere kopyalanıp paylaşılır; azaltma: dosya `/root` altında mod
|
||||
`600`, `--fetch` hedefi `admin/secrets/` git-ignore'lu (dizin `700`), parola yalnız
|
||||
dosyaya yazılır.
|
||||
KARAR: Şifre/kimlik bilgisi üretimi OPSİYONELDİR ve VARSAYILAN OLARAK KAPALIDIR; yalnız `bf-creds --generate` açıkça istendiğinde üretilir ve parola hiçbir zaman ekrana/loga/komut satırına yazılmaz.
|
||||
GEREKÇE: SSH zaten anahtar zorunludur (parola girişi kapalı, `blueforce` hesabı kilitli — K-13); kullanılmayan bir parola üretmek sızma yüzeyini büyütür. Varsayılan kapalı olması secret'ın git'e/medyaya/support bundle'a kaçmasını da baştan engeller.
|
||||
ALTERNATİF: Kurulumda otomatik parola üretimi — hiçbir kanal bu parolayı kullanmadığı için gereksiz secret üretir; elendi. Parolayı repoya/ISO'ya gömmek — secret yasağına aykırı; yasak.
|
||||
RİSK: Kayıt dosyası yanlış yere kopyalanıp paylaşılır; azaltma: dosya `/root` altında mod `600`, `--fetch` hedefi `admin/secrets/` git-ignore'lu (dizin `700`), parola yalnız dosyaya yazılır.
|
||||
MALİYET: Ücretsiz.
|
||||
LİSANS: Yok.
|
||||
```
|
||||
|
||||
## 4. Neden Bu Karar?
|
||||
|
||||
700 cihazlık bir filoda en pahalı hata, teknisyenin yanlış komutu yanlış cihazda çalıştırmasıdır. Grafik arayüz bu riski dört yerden küçültür: (1) operatör komut yazmaz, listeden doğru işlemi seçer; (2) her komut **çalıştırılmadan önce bir onay penceresinde** görünür ve onay ister — "ne çalışacak?" sorusu asla cevapsız kalmaz, komut çıktı alanına da ayrıca yazılır; (3) filo işlemleri hedefi üst çubuktan açıkça seçtirir (bayi no / dalga / tüm filo) ve dalga kapılarını (production için `production` yazma, sürüm kapısı için `GATE` yazma) operatöre ayrıca onaylatır; (4) yıkıcı işlemler ikinci bir onay penceresi ister ve yetki yoksa düğme yerine **çalıştırma katmanı** reddeder. Grafik arayüz aynı zamanda bir görünürlük kazancıdır: katalogda hangi işlemin kapsamı (`yerel — bu cihaz`, `filo — dalga kapılı`, `filo — sürüm kapılı`) ve türü (`salt-okunur` / `YIKICI`) olduğu listede renkli olarak durur.
|
||||
|
||||
Git tabanlı kurulum "hangi sürüm sahada?" sorusunu `git log` ile yanıtlanabilir kılar; kurulum paketlerinin depoda Git LFS ile durması ise "saha cihazı kurulurken ne indiriyor?" sorusunu **hiçbir şey** olarak yanıtlar. Şifre üretiminin varsayılan kapalı olması aynı felsefenin devamıdır: anahtar zaten var, ikinci bir gizli bilgi üretmenin faydası yok.
|
||||
700 cihazlık bir filoda en pahalı hata, teknisyenin yanlış komutu yanlış cihazda çalıştırmasıdır. Konsol bu riski üç yerden küçültür: (1) operatör komut yazmaz, doğru işlemi seçer; (2) her komut **çalıştırılmadan önce ekranda** görünür ve onay ister — "ne çalışacak?" sorusu asla cevapsız kalmaz; (3) filo işlemleri hedefi (`--limit`) açıkça seçtirir ve dalga kapılarını (production için `production`, release kapısı için `GATE` yazma) operatöre ayrıca onaylatır. Git tabanlı kurulum ise "hangi sürüm sahada?" sorusunu `git log` ile yanıtlanabilir kılar. Şifre üretiminin varsayılan kapalı olması aynı felsefenin devamıdır: anahtar zaten var, ikinci bir gizli bilgi üretmenin faydası yok.
|
||||
|
||||
## 5. Alternatifler
|
||||
|
||||
| Alternatif | Artı | Eksi | Sonuç |
|
||||
|---|---|---|---|
|
||||
| Grafik operatör uygulaması (`sudo bf`, tkinter) | En keşfedilebilir; komutu gösterip onay ister; hedef ve kapılar tek ekranda; denetim kaydı tutar; çevrimdışı çalışır | Grafik oturum gerekir; tkinter paketi (depoda pinli) | **Seçildi** |
|
||||
| Terminal konsolu (`sudo bf --tui`, aynı `bfos` iş mantığı) | Grafik ekran gerektirmez; SSH/başsız oturumda çalışır | Numara yazmaya dayanır, daha az keşfedilebilir | Yedek (grafik açılamazsa önerilir) |
|
||||
| Eski bash konsolu (`admin/bf-menu`) | Python'suz cihazda da çalışır | Ayrı bir katalog tablosu; iki giriş noktası zamanla ayrışır | Yedek (son çare) |
|
||||
| Numaralı kategori konsolu (`bf-menu`) | Keşfedilebilir, komutu gösterip onay ister, çevrimdışı çalışır, denetim log'u tutar | Konsol tablosu playbook'la senkron tutulmalı | **Seçildi** |
|
||||
| Dokümandan komut kopyalama | Araç gerektirmez | Sıra atlama + yanlış hedef riski | Elendi |
|
||||
| Yalnız Semaphore UI (web) | Güzel arayüz, merkezden yönetim | Saha cihazında çevrimdışı erişilemez; cihaz-kurulumunu kapsamaz | Merkez için korunur (09) |
|
||||
| Grafik masaüstü aracı (GUI uygulaması) | Görsel | Cihazlar terminale boot eder (K-03), ek bağımlılık ister | Elendi |
|
||||
| Tek düz komut scripti (`bf-do`) | Basit | Keşfedilebilirlik ve hedef seçimi yok, acemi için anlaşılmaz | Elendi |
|
||||
|
||||
## 6. Avantajlar
|
||||
|
||||
- Öğrenme maliyeti tek satır: `sudo bf`. Basit modda iki iş kararı yeter: `Kur`, `Durum`.
|
||||
- Her komut çalıştırılmadan önce onay penceresinde gösterilir; komut çıktı alanına da yazılır. Tehlikeli işlemler iki kez onaylanır — yanlış komut/yanlış sıra riski ortadan kalkar.
|
||||
- Katalogda 48 işlem vardır ve her birinin kapsamı ile türü listede görünür: **13 işlem yıkıcı (yazma)**, **35 işlem salt-okunur**. Yıkıcı satırlar listede kırmızı gösterilir (`YIKICI` / `salt-okunur` sütunu).
|
||||
- Filo işlemleri yalnız mevcut playbook'larla ve açık bir hedefle çalışır; arayüz **yeni playbook üretmez** ve envanter dışı bir cihaza dokunmaz.
|
||||
- Uzun süren işler arka planda koşar: çıktı canlı akar, pencere kilitlenmez, `Çalışanı iptal et` ile durdurulabilir.
|
||||
- Çevrimdışı çalışır — ISO/firstboot yoluna bağımlı değildir; kurulum paketleri de depodadır, saha cihazı hiçbir şey indirmez.
|
||||
- Grafik ekran yoksa uygulama Türkçe hata verip `sudo bf --tui` yolunu gösterir; operatör kör bırakılmaz.
|
||||
- Denetim kaydı (`/var/log/blueforce-console.log`, mod `600`) komutu, hedefi ve çıkış kodunu kaydeder; **secret ve ham komut çıktısı kayda yazılmaz** (tek bir temizleyici, `password=`/`token=`/`secret=`/`private_key=`/PEM bloklarını `<redacted>` yapar).
|
||||
- Öğrenme maliyeti tek satır: `sudo bf-menu`.
|
||||
- Her komut çalıştırılmadan önce gösterilir; tehlikeli işlemler iki kez onaylanır — yanlış komut/yanlış sıra riski ortadan kalkar.
|
||||
- Filo işlemleri yalnız mevcut playbook'larla ve açık `--limit` ile çalışır; konsol **yeni playbook üretmez** ve envanter dışı bir cihaza dokunmaz.
|
||||
- Çevrimdışı çalışır — ISO/firstboot yoluna bağımlı değildir.
|
||||
- Denetim log'u (`/var/log/blueforce-console.log`, mod `600`) komutu, hedefi ve çıkış kodunu kaydeder; **secret ve ham playbook çıktısı log'a yazılmaz**.
|
||||
|
||||
## 7. Dezavantajlar
|
||||
|
||||
- Katalog tablosu ile playbook'lar arasında kapsam (scope) uyuşmazlığı olursa komut üretilmez ve arayüz **çalıştırmayı reddeder**; bu, playbook güncellemesiyle katalog kaydının birlikte güncellenmesini zorunlu kılar.
|
||||
- Grafik arayüz bir pencere sistemine ihtiyaç duyar: `DISPLAY`/`WAYLAND_DISPLAY` yoksa (başsız sunucu, X yönlendirmesiz SSH) açılmaz — o durumda terminal konsoluna düşülür.
|
||||
- Cihaz işlemleri sekmesindeki filo işlemleri için makinede `ansible-playbook` gerekir; yoksa arayüz envanter notunda `UYARI: ansible-playbook bulunamadı; filo işlemleri çalışmaz` satırını gösterir ve komut üretilemez.
|
||||
- Çok özel/tek seferlik işler katalogda yoksa operatör kabuğa döner (kataloğa ekleme PR ile yapılır, `bfos/operations.py`).
|
||||
- Grafik katalog, terminal konsolunun kapsamının tamamını taşır: 48 işlemin hepsi `Detaylı mod` sekmelerinden erişilebilir (ölçüldü; `Araçlar` sekmesinde 9 işlem, `Cihaz bilgisi` sekmesinde ortam/kimlik/ağ/kaynak/servis ekranları). `sudo bf --tui` kolaylık için vardır, eksik bir yetenek için değil.
|
||||
- Her onay ayrı bir denetim satırı üretir; komutun ham çıktısı kayda kopyalanmaz (K-14).
|
||||
- Konsol tablosu ile playbook'lar arasında kapsam (scope) uyuşmazlığı olursa konsol çalıştırmayı reddeder; bu, playbook güncellemesiyle konsolun birlikte güncellenmesini zorunlu kılar (`admin/bf-menu` → `bf_playbook_check`).
|
||||
- Kategoriler 2, 3 ve 5-filo için makinede `ansible-playbook` gerekir; yoksa konsol açıklama verir ama işlemi çalıştırmaz.
|
||||
- Çok özel/tek seferlik işler konsol kataloğunda yoksa operatör kabuğa döner (kataloğa ekleme PR ile yapılır).
|
||||
- TUI çıktısı log'a birebir kopyalanmaz; her seçim ayrı bir denetim satırı üretir (K-14).
|
||||
|
||||
## 8. Riskler
|
||||
|
||||
| Risk | Olasılık | Etki | Azaltma |
|
||||
|---|---|---|---|
|
||||
| Katalog bayatlar, yanlış kapıyla çalıştırır | Orta | Yüksek | Komut üretimi playbook kapsamını dosyadan okur, uyuşmazlıkta reddeder; statik testler katmanında katalog↔playbook doğrulaması her sürümde koşar |
|
||||
| Konsol bayatlar, yanlış kapıyla çalıştırır | Orta | Yüksek | `bf_playbook_check` kapsam karşılaştırması uyuşmazlıkta reddeder; §10 testi her sürümde koşar |
|
||||
| Operatör "tüm filo" hedefini yanlışlıkla seçer | Orta | Yüksek | Wave-scoped playbook'larda filo dalga dalga ilerler, her dalga **ayrı onaylanır**; production için `production` yazma zorunlu (09/10) |
|
||||
| Yetkisiz oturumda yazma işlemi denenir | Orta | Orta | Açılışta başlıkta uyarı şeridi; yazma işlemleri kapalı ve çalıştırma katmanı da reddeder (`[ENGELLENDİ]`), §9.8 |
|
||||
| Grafik arayüz açılamaz (başsız/X yok) | Orta | Orta | Türkçe hata + `sudo bf --tui` önerisi, çıkış kodu 3; terminal konsolu aynı iş mantığını kullanır |
|
||||
| `python3-tk` imajda eksik kalır | Düşük | Orta | Paket çevrimdışı depoda pinli; kurulum sonu kapısı tkinter'ı denetler ve eksikse WARN + `--tui` yolu yazar |
|
||||
| `curl \| bash` ile sahte script çalıştırma | Düşük | Yüksek | Yalnız resmi depo adresi; `git clone` + gözden geçirme önerilir |
|
||||
| `curl | bash` ile sahte script çalıştırma | Düşük | Yüksek | Yalnız resmi depo adresi; `git clone` + gözden geçirme önerilir |
|
||||
| Şifre kaydı yanlışlıkla paylaşılır | Düşük | Yüksek | Varsayılan kapalı; `/root/blueforce-credentials.txt` mod `600`; `admin/secrets/` git-ignore'lu (§9.5) |
|
||||
| İşlem yarıda kalkar (elektrik) | Orta | Orta | Kurulum idempotent; `Kurulum → Başarısız kuruluma devam et` (`--resume`) sunulur (§11) |
|
||||
| Arayüz, envanter dışı cihaza dokunur | Düşük | Yüksek | Hedefler envanterden çözülür; cihaz/grup bulunamazsa komut üretilmez |
|
||||
| İşlem yarıda kalkar (elektrik) | Orta | Orta | Kurulum idempotent; menü "Resume after a failed run" sunar (§9.6) |
|
||||
| Konsol, envanter dışı cihaza dokunur | Düşük | Yüksek | Hedefler envanterden çözülür; cihaz/grup bulunamazsa işlem reddedilir |
|
||||
|
||||
## 9. Uygulama Planı
|
||||
|
||||
|
|
@ -168,7 +101,7 @@ Bu bölüm sıfırdan başlayan içindir. Her adımda **hangi komutu nereye yaza
|
|||
|
||||
- Ubuntu Server tabanlı bir makine (desteklenen baseline `24.04` / `26.04`).
|
||||
- `sudo` yetkisi olan bir kullanıcı.
|
||||
- Kurulum başlangıcında **internet** (repoyu git'ten indirmek için). Kurulum paketleri deponun içinde geldiği için cihaza kurulan hiçbir şey indirilmez; cihaz kurulduktan sonra çalışması için internet gerekmez.
|
||||
- Kurulum sırasında **internet** (repoyu git'ten indirmek için). Cihaz kurulduktan sonra çalışması için internet gerekmez.
|
||||
|
||||
**Adım 1 — Terminali aç.** Ekranda şöyle bir satır görürsün:
|
||||
|
||||
|
|
@ -199,7 +132,7 @@ git clone https://github.com/emirhanmamak-blueforce/Blueforce-Linux.git
|
|||
cd Blueforce-Linux
|
||||
```
|
||||
|
||||
Ekranda `Cloning into 'Blueforce-Linux'...` görürsün ve komut `$` satırına döner. Depo Git LFS kullandığı için kurulum paket setinin de indiğinden emin ol (`git lfs pull`); paket sayısı `provisioning/offline-repo/packages/` altında **1321** `.deb` olmalıdır.
|
||||
Ekranda `Cloning into 'Blueforce-Linux'...` görürsün ve komut `$` satırına döner.
|
||||
|
||||
**Adım 4 — Bootstrap'ı çalıştır.** İki yol var, ikisi de aynı sonucu verir.
|
||||
|
||||
|
|
@ -215,22 +148,26 @@ sudo admin/bf-bootstrap.sh
|
|||
curl -fsSL https://raw.githubusercontent.com/emirhanmamak-blueforce/Blueforce-Linux/main/admin/bf-bootstrap.sh | sudo bash
|
||||
```
|
||||
|
||||
> `sudo admin/bf-bootstrap.sh --check` **hiçbir şeyi değiştirmeden** ne yapılacağını raporlar (root bile gerekmez). Önce bunu çalıştırmak iyi alışkanlıktır.
|
||||
|
||||
Bootstrap `bf-*` araçlarını `/usr/local/bin`'e bağlar ve **grafik arayüz girişini** hazırlar; kendi özet çıktısında iki konsolu ayrı satırlarda bildirir: `console : /usr/local/bin/bf (Python, primary)` ve `fallback : /usr/local/bin/bf-menu (bash)`. Son satırlar:
|
||||
Bootstrap ne yapar (kendi özet çıktısı, örnek):
|
||||
|
||||
```text
|
||||
bf-bootstrap: ubuntu 26.04 is a supported baseline
|
||||
bf-bootstrap: dependency check
|
||||
bf-bootstrap: dependencies present: git curl ansible-playbook
|
||||
bf-bootstrap: cloning https://github.com/emirhanmamak-blueforce/Blueforce-Linux.git (branch main) into /opt/blueforce-linux
|
||||
bf-bootstrap: linked 26 tools into /usr/local/bin
|
||||
bf-bootstrap: bf-menu ready: /usr/local/bin/bf-menu
|
||||
|
||||
bf-bootstrap: summary
|
||||
repository : /opt/blueforce-linux
|
||||
branch : main
|
||||
revision : <git hash>
|
||||
tools : <N> linked into /usr/local/bin
|
||||
console : /usr/local/bin/bf (Python, primary)
|
||||
fallback : /usr/local/bin/bf-menu (bash)
|
||||
next : sudo bf
|
||||
tools : 26 linked into /usr/local/bin
|
||||
bf-menu : /usr/local/bin/bf-menu
|
||||
next : sudo bf-menu
|
||||
|
||||
Installation complete. To get started: sudo bf
|
||||
Kurulum tamam. Başlamak için: sudo bf
|
||||
Installation complete. To get started: sudo bf-menu
|
||||
Kurulum tamam. Başlamak için: sudo bf-menu
|
||||
```
|
||||
|
||||
| Bootstrap ne yapar | Ne yapmaz |
|
||||
|
|
@ -238,271 +175,297 @@ Kurulum tamam. Başlamak için: sudo bf
|
|||
| Ön koşulları kurar (`git`, `curl`, `ansible-core`) | Cihaz kimliği (bayi no) atamaz |
|
||||
| Repoyu klonlar veya mevcut checkout'u **fast-forward** eder | `git reset` / `git stash` yapmaz; yerel değişikliği **silmez** |
|
||||
| `admin/bf-*`, `scripts/diagnostics/bf-*`, `scripts/maintenance/bf-*` araçlarını `/usr/local/bin`'e bağlar | Parola/secret üretmez veya indirmez |
|
||||
| `admin/bf`'yi çalıştırılabilir yapıp `/usr/local/bin/bf` bağını kurar (`bf-menu` yedek olarak kalır) | Disk bölmez, servis silmez, onaysız paket güncellemez |
|
||||
| `admin/bf-menu`'yü çalıştırılabilir yapıp `sudo bf-menu`'yü hazırlar | Disk bölmez, servis silmez, onaysız paket güncellemez |
|
||||
|
||||
**Adım 5 — Arayüzü aç ve doğrula.**
|
||||
> `sudo admin/bf-bootstrap.sh --check` **hiçbir şeyi değiştirmeden** ne yapılacağını raporlar (root bile gerekmez). Önce bunu çalıştırmak iyi alışkanlıktır.
|
||||
|
||||
**Adım 5 — Menüyü aç ve doğrula.**
|
||||
|
||||
```bash
|
||||
sudo bf
|
||||
sudo bf-menu
|
||||
```
|
||||
|
||||
Pencere açılıyorsa kurulum tamam. Bundan sonra her iş için aynı komut:
|
||||
Menü açılıyorsa kurulum tamam. Bundan sonra her iş için aynı komut:
|
||||
|
||||
```bash
|
||||
sudo bf
|
||||
sudo bf-menu
|
||||
```
|
||||
|
||||
> **Bundan sonra ezberleyeceğin tek şey bu komuttur.** Pencereden çıkmak için `Çıkış` düğmesi (basit modda üçüncü düğme, alt çubukta da bir `Çıkış` düğmesi var).
|
||||
> **Bundan sonra ezberleyeceğin tek şey bu komuttur.** Menüden çıkmak için ana ekranda `q`; alt menülerde önce `0` (geri), sonra `q` (çıkış).
|
||||
|
||||
**tkinter notu (grafik arayüz için gerekli).** Pencerenin açılabilmesi için `python3-tk` paketi gerekir. Bu paket **çevrimdışı depoda pinlidir** (`provisioning/offline-repo/manifests/base-packages.txt`), yani normal kurulumda senin bir şey yapmana gerek yoktur; kurulum sonu kapısı (`scripts/install/installer/modules/18-final-check.sh`) tkinter'ı denetler. Yine de eksikse uygulama şu Türkçe hatayı verir ve çıkış kodu `3` ile biter:
|
||||
### 9.2 Menüyü kullanma — kategori kategori
|
||||
|
||||
`sudo bf-menu` çalıştırınca **ana menü** açılır. Bir numara yazıp Enter'a bas.
|
||||
|
||||
**Ana menü (örnek ekran):**
|
||||
|
||||
```text
|
||||
tkinter bulunamadı; masaüstü arayüzü başlatılamıyor (teknik ayrıntı: ...).
|
||||
==============================================================================
|
||||
Blueforce operator console 1.0.0
|
||||
repo: /opt/blueforce-linux
|
||||
==============================================================================
|
||||
|
||||
Bu, minimal kurulumlarda sık görülür: tkinter ayrı bir sistem paketidir.
|
||||
Ubuntu/Debian üzerinde kurmak için:
|
||||
Categories
|
||||
|
||||
sudo apt install -y python3-tk
|
||||
sudo apt update && sudo apt install -y python3-tk
|
||||
1) Installation this device, local one-click installer
|
||||
2) Device operations fleet playbooks, explicit target
|
||||
3) Central (preparation) verify and prepare central integration
|
||||
4) Tools repository and local helpers
|
||||
5) Device information read-only information screens
|
||||
|
||||
tkinter kurmak istemiyorsanız terminal menüsünü kullanın: sudo bf --tui
|
||||
------------------------------------------------------------------------------
|
||||
q) Quit the console
|
||||
Log: /var/log/blueforce-console.log
|
||||
------------------------------------------------------------------------------
|
||||
Choice >
|
||||
```
|
||||
|
||||
İnternet yoksa paketi kuramazsın; **terminal konsolu çalışmaya devam eder**: `sudo bf --tui`.
|
||||
Kategori kategori ne yapar ve hangi soruları sorar:
|
||||
|
||||
**Grafik ekran yoksa (SSH / başsız oturum).** `DISPLAY` ve `WAYLAND_DISPLAY` tanımlı değilse pencere açılmaz; uygulama şu Türkçe mesajı yazıp çıkış kodu `3` ile biter:
|
||||
**1) Installation (bu cihaz)** — yalnız **senin oturduğun makineyi** kurar; hiçbir filo cihazına dokunmaz.
|
||||
|
||||
```text
|
||||
Grafik ekran bulunamadı (DISPLAY ve WAYLAND_DISPLAY tanımlı değil).
|
||||
|
||||
SSH veya başsız (headless) bir oturumda masaüstü penceresi açılamaz.
|
||||
Bu durumda terminal menüsünü kullanın:
|
||||
|
||||
sudo bf --tui
|
||||
|
||||
Yerel ekranda çalıştırmak için oturum açık bir makinede deneyin:
|
||||
python3 -m bfos.ui_gui
|
||||
1) Pre-flight check installer --check, writes nothing
|
||||
2) Install this device full run, asks dealer number
|
||||
3) Resume after a failed run installer --resume
|
||||
4) Run a single module installer --only
|
||||
5) Show module state /var/lib/blueforce/install-state
|
||||
6) Show the installer log tail of /var/log/blueforce-install.log
|
||||
```
|
||||
Sorduğu sorular: **`Dealer number (8 digits) >`**; 2. ve 3. seçenekte ayrıca "offline repo'dan mı kurulsun?" ve "zaten OK olan modüller atlansın mı?" onayları; son olarak **`Run this command? [y=run / c=run with --check / N=cancel]`**. 2, 3 ve 4 numaralı seçenekler `root` ister (konsolu `sudo` ile açtıysan hazırdır). Format yanlışsa (`^[0-9]{8}$` uymuyorsa) konsol kurulumu başlatmaz.
|
||||
|
||||
### 9.2 Arayüzü kullanma — sekme sekme
|
||||
|
||||
`sudo bf` çalıştırınca **basit mod** açılır. Başlıkta `Blueforce Field OS — Yönetim`, altında `Blueforce saha cihazı yönetimi (Kur / Durum / Bakım)`, ardından depo yolu ve kullanılan katalog kaynağı (gerçek iş mantığı katmanı, örn. `bfos.operations + bfos.runner`) görünür.
|
||||
|
||||
**Basit mod (varsayılan):** ekranda `Ne yapmak istiyorsunuz?` sorusu ve üç büyük düğme — `Kur`, `Durum`, `Çıkış`. `Kur` bir seçim penceresi açar: `Ön kontrol (--check)`, `Kurulumu başlat`, `Vazgeç`. `Durum` salt-okunur özeti (`info-summary`) çalıştırır. Daha fazlası için üst çubuktaki **`Detaylı mod`** düğmesine bas.
|
||||
**2) Device operations (filo)** — yalnız repodaki **mevcut** playbook'ları, açık bir hedefle çalıştırır.
|
||||
|
||||
```text
|
||||
Ne yapmak istiyorsunuz?
|
||||
|
||||
[ Kur ] bu cihazı kurar (bayi no gerekir)
|
||||
[ Durum ] salt-okunur özet
|
||||
[ Çıkış ] pencereyi kapatır
|
||||
1) Read-only reports 11 operations, no change on any device
|
||||
2) Maintenance actions 10 operations, some destructive
|
||||
3) Show inventory targets groups, hosts and counts
|
||||
```
|
||||
|
||||
**Detaylı mod:** 5 kategori **sekmesi** açılır. Her sekmede solda işlem listesi (sütunlar: `İşlem`, `Kapsam`, `Tür`), sağda `Seçenekler ve açıklama` paneli vardır; seçtiğin işlemin kapsamı, playbook yolu ve varsa zorunlu alanları orada görünür. Alt çubukta `Komutu göster ve çalıştır`, `Çıktıyı temizle`, `Çalışanı iptal et`, `Yalnız denetim (--check)`, `Çıkış` ve durum etiketi (`Hazır.`) bulunur.
|
||||
|
||||
| Sekme | İşlem sayısı | Yazma (yıkıcı) | Salt-okunur |
|
||||
|---|---|---|---|
|
||||
| **Kurulum** | 6 | 3 (`Bu cihazı kur`, `Başarısız kuruluma devam et`, `Tek modül çalıştır`) | 3 (ön kontrol, modül durumu, kurulum günlüğü) |
|
||||
| **Cihaz işlemleri** | 21 | 9 (servis yeniden başlatmalar, grafik oturumu aç/kapat, betik, reboot, paket güncellemesi) | 12 (11 filo raporu + log toplama) |
|
||||
| **Merkez hazırlığı** | 4 | 0 | 4 |
|
||||
| **Araçlar** | 9 | 1 (`Bu kopyayı güncelle`) | 8 |
|
||||
| **Cihaz bilgisi** | 8 | 0 | 8 |
|
||||
| **Toplam** | **48** | **13** | **35** |
|
||||
|
||||
Sekme sekme hangi işler var:
|
||||
|
||||
**1) Kurulum (bu cihaz)** — yalnız **senin oturduğun makineyi** kurar; hiçbir filo cihazına dokunmaz. Üst çubukta **bayi no (8 hane)** dolu olmalıdır; boşsa `Komutu göster ve çalıştır` bir uyarı penceresi açar.
|
||||
|
||||
| # | İşlem (arayüzde görünen ad) | Tür | Ne yapar |
|
||||
|---|---|---|---|
|
||||
| 1 | Kurulum ön kontrolü (--check) | salt-okunur | Kurulum betiğini `--check` ile çalıştırır; hiçbir şey yazmaz (kayıt/durum/dizin oluşturmaz) |
|
||||
| 2 | Bu cihazı kur | **YIKICI** | Tam kurulum; hedef cihaz kimliği `BF-<bayi no>`, ana makine adı `bf-<bayi no>` |
|
||||
| 3 | Başarısız kuruluma devam et (--resume) | **YIKICI** | Yarıda kalan kurulumu idempotent biçimde sürdürür; zaten `OK` olan modüller atlanır |
|
||||
| 4 | Tek modül çalıştır (--only) | **YIKICI** | Tek bir kurulum modülünü çalıştırır (`01-precheck` … `18-final-check`), modül adı seçenekten girilir |
|
||||
| 5 | Kurulum modül durumu | salt-okunur | `/var/lib/blueforce/install-state` içeriğini gösterir: hangi modül hangi durumda |
|
||||
| 6 | Kurulum günlüğü (son 40 satır) | salt-okunur | `/var/log/blueforce-install.log` sonunu gösterir |
|
||||
|
||||
Kurulum seçenekleri: `Yerel çevrimdışı depodan kur (--offline)` ve `Zaten OK olan modülleri atla (--resume)` onay kutuları. Kurulum paketleri deponun içinde olduğu için **--offline pratikte varsayılan yoldur**; cihaz hiçbir şey indirmez. Geçersiz bayi no'da (7/9 hane, harf, boşluk) komut hiç üretilmez: üst çubukta kırmızı uyarı çıkar ve `Komutu göster ve çalıştır` bir hata penceresi açar.
|
||||
|
||||
**2) Cihaz işlemleri (filo)** — yalnız repodaki **mevcut** playbook'ları, açık bir hedefle çalıştırır. Üst çubuktan bayi no, dalga ya da `Tüm filo (dikkat)` seçilir.
|
||||
|
||||
*Salt-okunur raporlar (11 işlem, hiçbiri cihazı değiştirmez):*
|
||||
*2.1 Read-only fleet reports (11 işlem, hiçbiri cihazı değiştirmez):*
|
||||
|
||||
| # | İşlem | Ne yapar |
|
||||
|---|---|---|
|
||||
| 1 | Erişilebilirlik testi (ping) | SSH erişilebilirliği |
|
||||
| 2 | Çalışma süresi | Açık kalma süresi ve sistem yükü |
|
||||
| 3 | Disk kullanımı | Disk doluluğu; eşik üstünde uyarır (eşik opsiyonel girilir) |
|
||||
| 4 | Docker durumu | Docker servisi ve konteynerler |
|
||||
| 5 | Paket sürümleri | Sabitlenmiş paketlerin kurulu sürümleri |
|
||||
| 6 | Bekleyen güvenlik güncellemeleri | **Yalnız rapor**; hiçbir paket kurmaz |
|
||||
| 7 | Kurulum fazı raporu | Cihaz başına `state.json` fazı |
|
||||
| 8 | Kayıt ve merkez kanıtı | ENROLLED/READY iddialarını merkezi kanıta karşı denetler |
|
||||
| 9 | Field OS sürüm raporu | Sürüm; istenirse sapma (drift) denetimi |
|
||||
| 10 | Uzak erişim kanalları | SSH/xRDP/RustDesk/WireGuard hazırlığı |
|
||||
| 11 | Çevrimdışı hazırlık raporu | İnternetsiz kurulum için yerel ön koşullar |
|
||||
| 1 | Ping / reachability | SSH erişilebilirliği (salt-okunur) |
|
||||
| 2 | Uptime | Çalışma süresi ve yük |
|
||||
| 3 | Disk usage | Disk kullanımı; eşik üstünde uyarır (eşik sorulur) |
|
||||
| 4 | Docker status | Docker servisi ve konteynerler |
|
||||
| 5 | Package versions | Pinlenmiş paketlerin kurulu sürümleri |
|
||||
| 6 | Pending security updates | **Yalnız rapor**; asla kurmaz |
|
||||
| 7 | Provisioning phase report | Cihaz başına `state.json` fazı |
|
||||
| 8 | Enrollment + central evidence | ENROLLED/READY iddialarını merkezi kanıta karşı denetler |
|
||||
| 9 | Field OS version report | Sürüm; istenirse drift kontrolü (beklenen sürüm sorulur) |
|
||||
| 10 | Remote access channels | SSH/xRDP/RustDesk/WireGuard hazırlığı |
|
||||
| 11 | Offline readiness report | Offline provisioning yerel ön koşulları |
|
||||
|
||||
*Bakım işlemleri (10 işlem; 9'u yıkıcı, hepsi ikinci onay ister):*
|
||||
*2.2 Fleet maintenance (10 işlem, bir kısmı yıkıcı):*
|
||||
|
||||
| İşlem | Kapsam | Not |
|
||||
| # | İşlem | Not |
|
||||
|---|---|---|
|
||||
| xRDP servisini yeniden başlat | tek cihaz/grup | Servis yeniden başlatma |
|
||||
| RustDesk servisini yeniden başlat | tek cihaz/grup | Servis yeniden başlatma |
|
||||
| WireGuard servisini yeniden başlat | tek cihaz/grup | `wg-quick@wg0` |
|
||||
| İzinli bir servisi yeniden başlat | tek cihaz/grup | Yalnız izinli servis adları (`blueforce-agent`, `docker`, `ssh`, `sshd`, `systemd-journald`, `cron`) |
|
||||
| Grafik arayüzü kapat (headless) | dalga kapılı | Dalgayı `multi-user.target`'e alır |
|
||||
| Grafik arayüzü aç (bakım) | dalga kapılı | Grafik oturumu yeniden başlatır |
|
||||
| Log topla / destek paketi | dalga kapılı | Zaman damgalı journal + destek paketi (salt-okunur) |
|
||||
| Onaylı betik çalıştır | dalga kapılı | Yalnız `/opt/blueforce/bin` ve `/usr/local/sbin` |
|
||||
| Kontrollü yeniden başlatma | sürüm kapılı | Sıralı yeniden başlatma + sağlık kapısı; bekleme süresi girilir |
|
||||
| Onaylı paket güncellemesi kur | sürüm kapılı | `paket=sürüm` pinleri + dalga ve sağlık kapıları |
|
||||
| 1–3 | Restart RDP / RustDesk / WireGuard | Servis yeniden başlatma |
|
||||
| 4 | Restart an allowlisted service | Yalnız izinli servis adları (`blueforce-agent`, `docker`, `ssh`, `sshd`, `systemd-journald`, `cron`) |
|
||||
| 5 | GUI off (headless) | Dalgayı `multi-user.target`'e alır |
|
||||
| 6 | GUI on (maintenance) | Grafik oturumu geri açar |
|
||||
| 7 | Collect logs / support bundle | Zaman damgalı journal + snapshot paketi (satır sayısı sorulur) |
|
||||
| 8 | Run an approved script | Yalnız `/opt/blueforce/bin` ve `/usr/local/sbin` |
|
||||
| 9 | Controlled reboot | Seri yeniden başlatma + sağlık kapısı (bekleme süresi sorulur) |
|
||||
| 10 | Deploy approved package update | `package=version` pinleri + sağlık kapısı |
|
||||
|
||||
> **`GUI kapat` xRDP'i durdurmaz.** `xrdp`/`xrdp-sesman` her zaman enable+active kalır; `bf-gui-*` yalnız **yerel fiziksel** grafik katmanını kontrol eder (K-22). "GUI kapalı ≠ RDP kapalı."
|
||||
> **`bf-gui-off` xRDP'i durdurmaz.** `xrdp`/`xrdp-sesman` her zaman enable+active kalır; `bf-gui-*` yalnız **yerel fiziksel** grafik katmanını kontrol eder (K-22). "GUI kapalı ≠ RDP kapalı."
|
||||
|
||||
**3) Merkez hazırlığı** — merkez entegrasyonunu **denetler/hazırlar**; merkez sunucusunu **kurmaz**. Dört işlemin tamamı salt-okunurdur:
|
||||
|
||||
| # | İşlem | Ne gösterir |
|
||||
|---|---|---|
|
||||
| 1 | Envanter hedefleri | Dalga/grup/cihaz sayıları |
|
||||
| 2 | Doldurulmamış PLACEHOLDER denetimi | `ansible/inventory/group_vars/all.yml` içinde kalan PLACEHOLDER değerleri |
|
||||
| 3 | Yapılandırılmış merkez uç noktaları | WireGuard hub, izleme ve depo anahtarları (**secret gösterilmez**) |
|
||||
| 4 | Merkez hazırlık kontrol listesi | Kayıttan önce merkezde var olması gerekenler |
|
||||
|
||||
> `--tui` menüsünde bu sekmenin karşılığında ayrıca "Merkez hazırlık durumu", "uç noktaları dene" (DNS+TCP) ve "dalga geçiş kapısı durumu" ekranları vardır.
|
||||
|
||||
**4) Araçlar** — repo ve yerel yardımcılar. Yalnız `Bu kopyayı güncelle (git pull --ff-only)` yazma işlemidir; kalan 8'i salt-okunurdur: `İşlem kataloğunu göster (--list)`, `Yerel çevrimdışı kapısı (bf-check-local)`, `Kayıt kapısı (bf-check-enrollment)`, `Teslim kapısı (bf-check-ready)`, `Derin teşhis (bf-diagnostics)`, `Field OS sürüm kimliği (bf-release)`, `Destek paketi oluştur`, `Konsol denetim günlüğü (son 40 satır)`.
|
||||
|
||||
**5) Cihaz bilgisi** — sekiz salt-okunur ekran: `Durum özeti (sağlık + kurulum durumu)`, `Kimlik (hostname, cihaz no)`, `Ağ (adres, rota, DNS, WireGuard)`, `Disk, bellek, yük`, `Kurulu pinlenmiş paketler`, `Servis durumu`, `Son journal hataları`, `Kurulum/kayıt durumu (state.json beyaz liste)`.
|
||||
|
||||
> **Not (WireGuard):** Arayüz WireGuard private/preshared key'lerini **hiçbir zaman istemez, göstermez veya kaydetmez**; yalnız peer durumunu, port ve el sıkışma zamanlarını okur.
|
||||
|
||||
### 9.3 Hedef seçimi: tek cihaz mı dalga mı
|
||||
|
||||
Filo işlemlerinde hedef **üst çubuktan** seçilir; işlem seçildiğinde ekran hedefi ayrıca sormaz, çubuktaki değeri kullanır:
|
||||
**3) Central (preparation)** — merkez entegrasyonunu **denetler/hazırlar**; merkez sunucusunu **kurmaz**.
|
||||
|
||||
```text
|
||||
[Detaylı mod] Hedef: [ 12010193 ] Bayi no (8 hane) [ pilot_1 ▾ ] Dalga [ ] Tüm filo (dikkat)
|
||||
1) Central readiness report inventory, placeholders, admin key
|
||||
2) Show configured central endpoints WireGuard hub, monitoring, mirror
|
||||
3) Probe central endpoints DNS + TCP, read-only
|
||||
4) Wave rollout gate state per-wave device counts and gate rules
|
||||
5) Central preparation checklist what must exist before enrollment
|
||||
```
|
||||
|
||||
| Hedef türü | Çubukta ne yaparsın | Örnek | Boyut | Tipik kullanım |
|
||||
**4) Tools** — repo ve yerel yardımcılar.
|
||||
|
||||
```text
|
||||
1) Update this checkout git pull --ff-only
|
||||
2) Environment and reference info paths, versions, resolved settings
|
||||
3) Show the operation catalogue --list output
|
||||
4) Local offline gate bf-check-local
|
||||
5) Enrollment gate bf-check-enrollment
|
||||
6) Ready gate bf-check-ready
|
||||
7) Deep diagnostics bf-diagnostics (or bf-status)
|
||||
8) Field OS release identity bf-release
|
||||
9) Hardware inventory bf-hardware-inventory.sh
|
||||
10) Support bundle bf-support-bundle --out-dir
|
||||
11) Show the console log last 40 lines of the audit log
|
||||
```
|
||||
|
||||
**5) Device information** — salt-okunur bilgi ekranları.
|
||||
|
||||
```text
|
||||
1) Identity hostname, device id, dealer number
|
||||
2) Health summary bf-status
|
||||
3) Provisioning and enrollment state state.json whitelist + bf-enrollment-status
|
||||
4) Network addresses, route, DNS, WireGuard peers
|
||||
5) Disk, memory, CPU df, free, load
|
||||
6) Installed pinned packages dpkg-query
|
||||
7) Service status ssh, xrdp, rustdesk, docker, wg, meshagent
|
||||
8) Recent journal errors journalctl -p err
|
||||
9) Inventory summary waves, groups, counts
|
||||
10) Resolve a target check a dealer number or group
|
||||
```
|
||||
|
||||
> **Not (WireGuard):** Konsol WireGuard private/preshared key'lerini **hiçbir zaman istemez, göstermez veya loglamaz**; yalnız peer durumunu okur.
|
||||
|
||||
### 9.3 Cihaz seçimi: tek cihaz mı grup mu
|
||||
|
||||
Kategori **2**'de bir işlem seçtiğinde konsol önce **hedefi** sorar:
|
||||
|
||||
```text
|
||||
Target selection (mode: wave)
|
||||
1) Single device by dealer number 8 digits, e.g. 12010101
|
||||
2) Group / wave lab, pilot_1, pilot_2, wave_1, wave_2, production
|
||||
3) All devices in the fleet asks per wave for wave-scoped playbooks
|
||||
9) Type the target directly dealer number, group or 'all'
|
||||
Target >
|
||||
```
|
||||
|
||||
| Hedef türü | Menüde ne yazarsın | Örnek | Boyut | Tipik kullanım |
|
||||
|---|---|---|---|---|
|
||||
| Tek cihaz | Bayi no alanına 8 hane yaz | `12010193` | 1 | Arıza teşhisi, tek cihaz bakımı |
|
||||
| Dalga / grup | `Dalga` açılır listesinden bir dalga seç | `lab` | 2 | Yeni playbook denemesi (önce LAB kuralı) |
|
||||
| Dalga / grup | `Dalga` listesi | `pilot_1` / `pilot_2` / `wave_1` / `wave_2` | 5 / 20 / 50 / 100 | Kademeli yayılım (K-11) |
|
||||
| Tüm filo | `Tüm filo (dikkat)` kutusunu işaretle | — | kalan | Yalnız onaylı; dalga dalga ilerler |
|
||||
| Tek cihaz | bayi no (8 hane) | `12010101` | 1 | Arıza teşhisi, tek cihaz bakımı |
|
||||
| Grup / dalga | grup adı | `lab` | 2 | Yeni playbook denemesi (önce LAB kuralı) |
|
||||
| Grup / dalga | grup adı | `pilot_1` / `pilot_2` / `wave_1` / `wave_2` | 5 / 20 / 50 / 100 | Kademeli yayılım (K-11) |
|
||||
| Tüm filo | `3` (veya doğrudan `all`) | — | kalan | Yalnız onaylı; dalga dalga ilerler |
|
||||
|
||||
Bayi no alanına yazdıkça anında doğrulanır; geçerliyse durum satırı `Bayi no geçerli: BF-12010193` yazar, geçersizse kırmızı uyarı görünür (örn. `Geçersiz bayi numarası '1201019': tam 8 hane olmalıdır (verilen uzunluk: 7). Örnek: 12010193`).
|
||||
Kurallar (konsolun kendi davranışı):
|
||||
|
||||
Kurallar (arayüzün kendi davranışı):
|
||||
- **Tek cihaz** normalde en güvenli seçenektir; cihaz envanterde yoksa konsol **reddeder** (`is not in the inventory`).
|
||||
- **Grup / dalga** seçiminde liste, her grubun cihaz sayısıyla ve onaylı dalga olup olmadığıyla gösterilir.
|
||||
- **Wave-scoped** bir playbook'ta tüm filo seçilirse konsol, dalgaları **sırayla** (`lab → pilot_1 → pilot_2 → wave_1 → wave_2 → production`) işler ve **her dalga için ayrı ayrı** onay ister; bir dalga başarısız olursa sonraki dalgaya **geçmez**.
|
||||
- **Release-gated** playbook'lar (reboot, deploy-update) tek cihaz veya tüm filo kabul etmez; **tek onaylı dalga** ister.
|
||||
- **production** dalgası ayrıca `production` yazdırılarak, release kapısı ise `GATE` yazdırılarak onaylanır. Hiçbir kapı sessizce geçilmez.
|
||||
|
||||
- **Tek cihaz** normalde en güvenli seçenektir; cihaz envanterde yoksa komut **üretilmez** (`... onaylı bir dalga grubunda değil` veya `envanterde yok`).
|
||||
- **Dalga / grup** listesi, envanterde gerçekten bulunan onaylı dalgalarla doldurulur; envanter okunamazsa varsayılan onaylı dalga sırası gösterilir.
|
||||
- **Wave-scoped** bir playbook'ta tüm filo seçilirse araç, dalgaları **sırayla** (`lab → pilot_1 → pilot_2 → wave_1 → wave_2 → production`) işler ve **her dalga için ayrı ayrı** onay ister; bir dalga başarısız olursa sonraki dalgaya **geçmez** (katalogdaki filo işlemleri ilk hatada durur).
|
||||
- **Release-gated** playbook'lar (reboot, paket güncellemesi) tek cihaz veya tüm filo kabul etmez; **tek onaylı dalga** ister.
|
||||
- **production** dalgası ayrıca `production` yazdırılarak, sürüm kapısı ise `GATE` yazdırılarak onaylanır. Hiçbir kapı sessizce geçilmez: onay pencereleri sırayla `PRODUCTION onayı — canlı filo`, `Production ek onayı`, `Sürüm kapısı onayı (dalga: <dalga>)`, `FİLO GENELİ onayı` (kutuya `all` yazılır) ve `İKİNCİ ONAY — yıkıcı işlem` başlıklarıyla açılır.
|
||||
### 9.4 Uçtan uca örnek seans (örnek ekran çıktısı)
|
||||
|
||||
### 9.4 Uçtan uca örnek seans
|
||||
|
||||
Aşağıdaki iki kısa seans, kurulumdan günlük işletime tipik akışı gösterir. Metin biçimleri uygulamanın kendi metinleridir; kurulum betiğinin kendi `[installer]` satırları LAB koşusunda eklenir.
|
||||
Aşağıdaki iki kısa seans, kurulumdan günlük işletime tipik akışı gösterir. (Çıktılar **örnektir**.)
|
||||
|
||||
**Seans A — Yeni cihazın kurulumu (bayi no girme)**
|
||||
|
||||
```text
|
||||
emirhan@makine:~$ sudo bf
|
||||
```
|
||||
emirhan@makine:~$ sudo bf-menu
|
||||
|
||||
Pencere açılır: `Blueforce Field OS — Yönetim` / `Blueforce saha cihazı yönetimi (Kur / Durum / Bakım)`.
|
||||
==============================================================================
|
||||
Blueforce operator console 1.0.0
|
||||
repo: /opt/blueforce-linux
|
||||
==============================================================================
|
||||
|
||||
1) Üst çubuktaki `Bayi no (8 hane)` alanına `12010193` yaz:
|
||||
Categories
|
||||
1) Installation 2) Device operations 3) Central (preparation)
|
||||
4) Tools 5) Device information
|
||||
|
||||
```text
|
||||
Hedef: [ 12010193 ] Bayi no (8 hane) [ lab ▾ ] Dalga [ ] Tüm filo (dikkat)
|
||||
durum: Bayi no geçerli: BF-12010193
|
||||
```
|
||||
------------------------------------------------------------------------------
|
||||
q) Quit the console
|
||||
Log: /var/log/blueforce-console.log
|
||||
------------------------------------------------------------------------------
|
||||
Choice > 1
|
||||
|
||||
2) Basit modda `Kur` düğmesine bas. Seçim penceresi açılır (başlık: `Kurulum`):
|
||||
==============================================================================
|
||||
1) Installation (this device)
|
||||
Local install only -- no fleet device is touched here
|
||||
==============================================================================
|
||||
|
||||
```text
|
||||
Bu cihazda ne yapılacak?
|
||||
1) Pre-flight check installer --check, writes nothing
|
||||
2) Install this device full run, asks dealer number
|
||||
3) Resume after a failed run installer --resume
|
||||
4) Run a single module installer --only
|
||||
5) Show module state /var/lib/blueforce/install-state
|
||||
6) Show the installer log tail of /var/log/blueforce-install.log
|
||||
|
||||
Ön kontrol (--check) hiçbir şey yazmaz; kurulum cihazı değiştirir.
|
||||
------------------------------------------------------------------------------
|
||||
0) Back q) Quit the console
|
||||
------------------------------------------------------------------------------
|
||||
Choice > 1
|
||||
Read-only pre-flight: the installer creates no log, state or directory in --check mode.
|
||||
Dealer number (8 digits) > 12010193
|
||||
|
||||
[ Ön kontrol (--check) ] [ Kurulumu başlat ] [ Vazgeç ]
|
||||
```
|
||||
Pre-flight check for BF-12010193
|
||||
|
||||
3) Önce `Ön kontrol (--check)` ile kuru koşu yapmak iyi alışkanlıktır: komut çıktı alanında görünür ve çalışır — hiçbir şey yazmaz.
|
||||
|
||||
```text
|
||||
========================================================================
|
||||
Çalıştırılıyor: Kurulum ön kontrolü (--check)
|
||||
bash /opt/blueforce-linux/scripts/install/blueforce-install.sh --dealer-id 12010193 --check
|
||||
========================================================================
|
||||
... (kurulum betiğinin kendi --check satırları) ...
|
||||
[OK] Komut başarıyla tamamlandı (çıkış kodu 0).
|
||||
|
||||
[1/18] precheck ........ OK [2/18] system ........ OK
|
||||
... [18/18] final-check ... OK
|
||||
|
||||
Press Enter to continue
|
||||
```
|
||||
|
||||
4) Şimdi gerçek kurulum: yeniden `Kur` → `Kurulumu başlat`. Komut, **çalışmadan önce** bir onay penceresinde gösterilir:
|
||||
Şimdi gerçek kurulum (aynı menüden **2**):
|
||||
|
||||
```text
|
||||
Çalıştırılacak komut(lar):
|
||||
Choice > 2
|
||||
Dealer number (8 digits) > 12010193
|
||||
Install from the local offline repository (--offline)? [y/N] n
|
||||
|
||||
bash /opt/blueforce-linux/scripts/install/blueforce-install.sh --dealer-id 12010193 --offline
|
||||
[i] Target device: BF-12010193 (bf-12010193)
|
||||
|
||||
İşlem : Bu cihazı kur [install-local]
|
||||
Kapsam : yerel — bu cihaz
|
||||
Açıklama: Cihazı kurar, hostname'i bf-<bayi-no> yapar.
|
||||
Hedef : cihaz BF-12010193 (bf-12010193)
|
||||
Yetki : root gerekir — konsolu sudo ile açın.
|
||||
Not : Hedef cihaz kimliği: BF-12010193 (bf-12010193).
|
||||
Command
|
||||
bash /opt/blueforce-linux/scripts/install/blueforce-install.sh --dealer-id 12010193
|
||||
|
||||
UYARI: Bu YIKICI bir işlemdir; seçili hedefte değişiklik yapar.
|
||||
[WARN] This is a DESTRUCTIVE operation: install on BF-12010193
|
||||
Proceed? [y=run / c=run with --check / N=cancel] y
|
||||
|
||||
Bu komut çalıştırılsın mı? [Evet] [Hayır]
|
||||
[1/18] precheck ..................... OK
|
||||
[2/18] system ....................... OK
|
||||
...
|
||||
[18/18] final-check .................. OK
|
||||
|
||||
[OK] Command finished successfully (exit 0).
|
||||
Press Enter to continue
|
||||
```
|
||||
|
||||
`Evet` dedikten sonra **ikinci onay** gelir (yıkıcı işlem), ardından komut çıktı alanına yazılır ve koşar:
|
||||
|
||||
```text
|
||||
========================================================================
|
||||
Çalıştırılıyor: Bu cihazı kur
|
||||
bash /opt/blueforce-linux/scripts/install/blueforce-install.sh --dealer-id 12010193 --offline
|
||||
========================================================================
|
||||
... (kurulum betiği yerel paket deposunu bulur, 18 modülü sırayla koşar) ...
|
||||
[OK] Komut başarıyla tamamlandı (çıkış kodu 0).
|
||||
```
|
||||
|
||||
Kurulum sonunda cihaz `PROVISIONED_OFFLINE` olur; **`READY` değildir** — merkeze kayıt (enrollment) ve merkezi kanal kanıtı gerekir (K-21). Bunu görmek için `Cihaz bilgisi` sekmesinden `Kurulum/kayıt durumu (state.json beyaz liste)` ya da `Durum özeti` açılır.
|
||||
Kurulum sonunda cihaz `PROVISIONED_OFFLINE` olur; **`READY` değildir** — merkeze kayıt (enrollment) ve merkezi kanal kanıtı gerekir (K-21). Bunu görmek için kategori **5 → 3** (Provisioning and enrollment state) açılır.
|
||||
|
||||
**Seans B — Günlük kontrol (salt-okunur rapor) ve teşhis paketi**
|
||||
|
||||
```text
|
||||
Üst çubuk: Hedef: [ 12010193 ] Dalga [ pilot_1 ▾ ]
|
||||
Detaylı mod → Cihaz işlemleri sekmesi → listeden "Erişilebilirlik testi (ping)" satırını seç
|
||||
Alt çubuk: [ Komutu göster ve çalıştır ]
|
||||
```
|
||||
Choice > 2
|
||||
|
||||
Onay penceresi:
|
||||
==============================================================================
|
||||
2) Device operations
|
||||
Existing playbooks only, always with an explicit target
|
||||
==============================================================================
|
||||
|
||||
```text
|
||||
Çalıştırılacak komut(lar):
|
||||
1) Read-only reports 11 operations, no change on any device
|
||||
2) Maintenance actions 10 operations, some destructive
|
||||
3) Show inventory targets groups, hosts and counts
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
0) Back q) Quit the console
|
||||
------------------------------------------------------------------------------
|
||||
Choice > 1
|
||||
|
||||
... 1) Ping / reachability 2) Uptime 3) Disk usage 4) Docker status ...
|
||||
|
||||
Choice > 1
|
||||
|
||||
Target selection (mode: any)
|
||||
1) Single device by dealer number 8 digits, e.g. 12010101
|
||||
2) Group / wave lab, pilot_1, pilot_2, wave_1, wave_2, production
|
||||
3) All devices in the fleet
|
||||
9) Type the target directly dealer number, group or 'all'
|
||||
Target > 1
|
||||
Dealer number (8 digits) > 12010193
|
||||
|
||||
Command
|
||||
ansible-playbook -i ansible/inventory/hosts.yml ansible/playbooks/bf-ping.yml --limit bf-12010193
|
||||
|
||||
İşlem : Erişilebilirlik testi (ping) [ping]
|
||||
Kapsam : filo — tek cihaz/grup (salt-okunur)
|
||||
Hedef : cihaz BF-12010193 (bf-12010193)
|
||||
Not : (playbook çıktısı canlı akar)
|
||||
Run this command? [y=run / c=run with --check / N=cancel] y
|
||||
|
||||
Bu komut çalıştırılsın mı? [Evet] [Hayır]
|
||||
PLAY [Ping / reachability] ...
|
||||
bf-12010193 | SUCCESS => {"changed": false, "ping": "pong"}
|
||||
|
||||
[OK] Command finished successfully (exit 0).
|
||||
```
|
||||
|
||||
Çıktı alanında playbook çıktısı canlı akar; iş bitince:
|
||||
|
||||
```text
|
||||
[OK] Komut başarıyla tamamlandı (çıkış kodu 0).
|
||||
```
|
||||
|
||||
Teşhis paketi için: `Araçlar` sekmesi → `Destek paketi oluştur`. Paket yolu çıktı alanında yazılır ve paket **parola, private key veya token içermez** (K-14). Denetim kaydını görmek için aynı sekmedeki `Konsol denetim günlüğü (son 40 satır)` açılır.
|
||||
Teşhis paketi için kategori **4 → 10** (Support bundle); paket yolu ekranda yazılır ve paket **parola, private key veya token içermez** (K-14).
|
||||
|
||||
### 9.5 Kimlik bilgileri / şifre dosyası (opsiyonel — varsayılan KAPALI)
|
||||
|
||||
|
|
@ -524,170 +487,125 @@ Teşhis paketi için: `Araçlar` sekmesi → `Destek paketi oluştur`. Paket yol
|
|||
|
||||
| # | Belirti (ekranda ne görürsün) | Neden | Çözüm |
|
||||
|---|---|---|---|
|
||||
| 1 | `bf: command not found` | Bootstrap çalışmamış veya araçlar bağlanmamış | Bootstrap'ı tekrar koş: `sudo admin/bf-bootstrap.sh`; sonra tam yoldan dene: `sudo /usr/local/bin/bf`. Python'suz cihazda yedek: `sudo bf-menu` |
|
||||
| 2 | Pencere açılıyor ama başlıkta turuncu şerit: `Yönetici yetkisi yok: salt-okunur raporlar çalışır, kurulum ve değişiklik gerektiren işlemler kapalıdır. Tam yetki için: sudo bf` | Arayüz `sudo` olmadan açıldı; yazma işlemleri kapalı | Pencereyi kapat ve `sudo bf` ile aç (§9.8) |
|
||||
| 3 | Hata penceresi: `Geçersiz bayi numarası '1201019': tam 8 hane olmalıdır (verilen uzunluk: 7). Örnek: 12010193` | Bayi no 8 haneli ve yalnız rakam olmalı | Tam 8 hane, sadece rakam gir; baştaki sıfırı silme. Örnek: `12010193` |
|
||||
| 4 | Envanter notunda `UYARI: ansible-playbook bulunamadı; filo işlemleri çalışmaz (sudo apt install ansible).` | Makinede Ansible yok | `sudo apt install ansible` (reponun kurulumu `ansible-core`'u zaten kurar) ve araçları bağla: `sudo admin/bf-bootstrap.sh` |
|
||||
| 5 | `Komut üretilemedi`: `Playbook bulunamadı: ansible/playbooks/...` veya `... konsol kapsamı 'X' beklerken playbook 'Y' beyan ediyor.` | Katalog ile repo checkout'u uyuşmuyor (eski checkout veya `--repo` yanlış) | `Araçlar` sekmesinden `Bu kopyayı güncelle (git pull --ff-only)` veya doğru repoyu ver: `sudo bf --repo /opt/blueforce-linux`; arayüzü yeniden başlat |
|
||||
| 1 | `bf-menu: command not found` | Bootstrap çalışmamış veya araçlar bağlanmamış | Bootstrap'ı tekrar koş: `sudo admin/bf-bootstrap.sh`; sonra `sudo /usr/local/bin/bf-menu` ile tam yoldan dene |
|
||||
| 2 | `[ERROR] This operation needs root on THIS device.` | Kurulum seçenekleri root ister; konsolu `sudo`'suz açtın | Konsolu `sudo bf-menu` ile aç (kural: bu işlem için konsol `Re-run the console with sudo: sudo admin/bf-menu` der) |
|
||||
| 3 | `[ERROR] Invalid dealer number '1201019': it must match ^[0-9]{8}$ (8 digits, no spaces).` | Bayi no 8 haneli ve yalnız rakam olmalı | Tam 8 hane, sadece rakam gir; baştaki sıfırı silme. Örnek: `12010193` |
|
||||
| 4 | `[WARN] ansible-playbook not found ... fleet operations cannot run.` veya `[WARN] ... is not available` | Makinede Ansible yok ya da araç PATH'te değil | `sudo apt install ansible` (reponun kurulumu `ansible-core`'u zaten kurar) ve araçları bağla: `sudo admin/bf-bootstrap.sh` |
|
||||
| 5 | `[ERROR] Playbook not found: ansible/playbooks/...` / `Refusing to run ... the console expects scope 'X' but the playbook declares 'Y'.` | Konsol ile repo checkout'u uyuşmuyor (eski checkout veya `--repo` yanlış) | Kategori **4 → 1** ile checkout'u güncelle (`git pull --ff-only`) veya doğru repoyu ver: `sudo bf-menu --repo /opt/blueforce-linux` |
|
||||
|
||||
Ek olarak sık görülen dört durum:
|
||||
Ek olarak sık görülen iki durum:
|
||||
|
||||
- **Grafik ekran yok** (`Grafik ekran bulunamadı (DISPLAY ve WAYLAND_DISPLAY tanımlı değil).`, çıkış kodu 3): Terminal konsolunu kullan: `sudo bf --tui`. Yerel ekranda oturum açık bir makinede `python3 -m bfos.ui_gui` çalışır.
|
||||
- **tkinter yok** (`tkinter bulunamadı; masaüstü arayüzü başlatılamıyor ...`): `sudo apt install -y python3-tk` (paket çevrimdışı depoda pinlidir) ya da `sudo bf --tui`.
|
||||
- **`Pencere açılamadı; grafik oturumuna erişilemiyor.`**: SSH oturumundasın ve X yönlendirmesi yok, ekran kilitli ya da başka bir kullanıcının X sunucusuna bağlanıyorsun; `sudo bf --tui` ile devam et.
|
||||
- **`git clone` internet/DNS hatası** (`Could not resolve host`): İnternet/DNS'i kontrol et; **yalnız bu adımda** internet gerekir. Kurulum paketleri depodadır, saha cihazı hiçbir şey indirmez.
|
||||
- **`git clone` internet/DNS hatası** (`Could not resolve host`): İnternet/DNS'i kontrol et; kurulum için internet yalnız bu adımda gerekir.
|
||||
- **`[ERROR] ... is not in the inventory`**: Cihaz veya grup `ansible/inventory`'de yok; hedefi envanterle eşle (02) veya `bf-bootstrap` ile checkout'u güncelle.
|
||||
|
||||
### 9.7 Güvenlik kuralları
|
||||
|
||||
1. **Secret git'e, ISO'ya veya destek paketine girmez.** Parola, private key ve token repoda/medyada bulunmaz; destek paketi çıktısı secret sızdırmaz (K-14). Denetim kaydı da tek bir temizleyiciden geçer: `password=`/`token=`/`secret=`/`api_key=`/`private_key=`/`psk=` değerleri ve PEM blokları `<redacted>` olur.
|
||||
2. **Onaysız update yoktur.** Güncelleme yalnız `Cihaz işlemleri` sekmesindeki `Onaylı paket güncellemesi kur` ile, `paket=sürüm` pinleri + dalga kapısı + sağlık kapısı altında yapılır (K-11). Serbest `apt upgrade`, `latest` imaj veya otomatik güncelleyici mimaride yoktur (`Bekleyen güvenlik güncellemeleri` **yalnız rapor**tur).
|
||||
3. **Yıkıcı işlemler onaylıdır.** Her komut çalıştırılmadan önce onay penceresinde gösterilir, onay istenir ve çıktı alanına da yazılır; yıkıcı işlemler ayrıca ikinci kez sorulur; onaylar eklendikten sonra komut değiştiyse **kesin komut** yeniden gösterilip onaylatılır. `production` dalgası için `production`, sürüm kapısı için `GATE`, tüm filo için `all` yazılması zorunludur. Disk bölme/silme arayüzde otomatikleştirilmemiştir.
|
||||
4. **Yetki kapısı çalıştırma katmanındadır.** Yetkisiz oturumda yazma işlemleri kapalıdır ve komut planı root gerektiriyorsa çalıştırma katmanı son savunma olarak reddeder (`[ENGELLENDİ]`); ayrıntı §9.8.
|
||||
5. **SSH yalnız anahtarla.** Parola girişi kapalı, `blueforce` hesabı kilitli; paylaşılan private key yasaktır (K-13).
|
||||
6. **Tek kullanımlık enrollment token kaydedilmez.** Token arayüz dışında bir kez girilir; denetim kaydı ham çıktıyı ve secret'ı yazmaz (K-17).
|
||||
7. **Cihaz kimliği imajda taşınmaz.** Bayi no yalnız ilk kurulum seansında üst çubuktaki alana girilir (K-09/K-12).
|
||||
|
||||
### 9.8 Yetki modeli
|
||||
|
||||
Arayüz beklenen kullanımda **tam yetkili** çalışır: `sudo bf`. Kurulum betiği dosya sistemine yazar, servisleri yönetir ve güvenlik duvarı temel çizgisini uygular; bu yüzden yazma işlemleri root ister. Ama arayüz root olmadan da **açılır** — çünkü raporlar repoyu ve envanteri okur, root gerektirmez.
|
||||
|
||||
| Durum | Ne olur |
|
||||
|---|---|
|
||||
| `sudo bf` (tam yetki) | 48 işlemin tamamı çalışır: kurulum, filo bakımı, paket güncellemesi, kontrollü reboot ve `--check` koşuları |
|
||||
| Root değil (yetkisiz açılış) | Başlıkta turuncu uyarı şeridi: `Yönetici yetkisi yok: salt-okunur raporlar çalışır, kurulum ve değişiklik gerektiren işlemler kapalıdır. Tam yetki için: sudo bf`. **35 salt-okunur işlem** çalışır (raporlar, envanter denetimi, bilgi ekranları, destek paketi); **13 yıkıcı işlem kapalıdır** |
|
||||
| Yetkisizken yazma denenirse | Yazma işlemleri düğme düzeyinde kapalıdır; bir yol bulunup denenirse **çalıştırma katmanı** reddeder ve çıktı alanına `[ENGELLENDİ] Bu işlem yönetici yetkisi gerektirir (sudo bf).` yazılır, işlem çalışmaz (çıkış kodu 2) |
|
||||
| `--check` kipi | Salt-okunur olduğu için yetki istemez: `Yalnız denetim (--check)` kutusu işaretliyse deneme koşusu yetkisiz oturumda da yapılabilir |
|
||||
|
||||
Hangi işlemler yetki ister: katalogda **13 yıkıcı işlem** — `Bu cihazı kur`, `Başarısız kuruluma devam et`, `Tek modül çalıştır` (Kurulum); servis yeniden başlatmalar (`xRDP`, `RustDesk`, `WireGuard`, izinli servis), `Grafik arayüzü kapat/aç`, `Onaylı betik çalıştır`, `Kontrollü yeniden başlatma`, `Onaylı paket güncellemesi kur` (Cihaz işlemleri); `Bu kopyayı güncelle` (Araçlar). Yetki kuralı tek kaynaktan türetilir: bir işlem yıkıcı olarak işaretliyse root gerektirir; ayrıca belirtildiyse o değer geçerlidir.
|
||||
|
||||
Planlama yetki istemez: komut önizlemesi, onay pencereleri ve `--check` üretimi root olmadan da çalışır, böylece operatör "bu benim yetkimle ne yapar?" sorusunu cevaplayabilir. Reddetme yalnız **gerçek çalıştırmaya** düşer.
|
||||
1. **Secret git'e, ISO'ya veya destek paketine girmez.** Parola, private key ve token repoda/medyada bulunmaz; `bf-support-bundle` çıktısı secret sızdırmaz (K-14).
|
||||
2. **Onaysız update yoktur.** Güncelleme yalnız kategori 2 → "Deploy approved package update" ile, `package=version` pinleri + dalga kapısı + sağlık kapısı altında yapılır (K-11). Serbest `apt upgrade`, `latest` imaj veya otomatik güncelleyici mimaride yoktur (kategori 2'de "Pending security updates" **yalnız rapor**tur).
|
||||
3. **Yıkıcı işlemler onaylıdır.** Her komut çalıştırılmadan önce ekranda gösterilir, onay istenir; yıkıcı işlemler ayrıca ikinci kez sorulur; production dalgası için `production` ve release kapısı için `GATE` yazılması zorunludur. Disk bölme/silme konsolda otomatikleştirilmemiştir.
|
||||
4. **SSH yalnız anahtarla.** Parola girişi kapalı, `blueforce` hesabı kilitli; paylaşılan private key yasaktır (K-13).
|
||||
5. **Tek kullanımlık enrollment token loglanmaz.** Token konsol dışında bir kez girilir; denetim log'u ham çıktıyı ve secret'ı yazmaz (K-17).
|
||||
6. **Cihaz kimliği imajda taşınmaz.** Bayi no yalnız ilk kurulum seansında girilir (K-09/K-12).
|
||||
|
||||
## 10. Test Planı
|
||||
|
||||
| Test | Beklenen sonuç | Ortam |
|
||||
|---|---|---|
|
||||
| `sudo admin/bf-bootstrap.sh` iki kez koşulur | İkinci koşu hata üretmez (idempotent), araçlar yerinde, `/usr/local/bin/bf` bağlı | LAB(2) |
|
||||
| `sudo bf --list` / `python3 -m bfos.ui_gui --list` | 48 işlem, 5 kategori, 13 YIKICI / 35 salt-okunur, pencere açılmadan listelenir | LAB(2) |
|
||||
| `sudo bf` açılır, `Çıkış` ile kapanır | Pencere açılır, hiçbir değişiklik yapılmaz | LAB(2) |
|
||||
| `sudo bf --tui` ile aynı işlem listesi | Terminal konsolu iki giriş noktası ayrışmadan çalışır | LAB(2) |
|
||||
| Grafik ekran olmadan (`env -u DISPLAY -u WAYLAND_DISPLAY sudo bf`) | Türkçe hata + `sudo bf --tui` önerisi, çıkış kodu `3` | LAB(2) |
|
||||
| tkinter'siz ortamda başlatma | Türkçe hata + `python3-tk` ipucu + `--tui` önerisi, çıkış kodu `3`; kurulum sonu kapısı bunu WARN olarak kaydeder | LAB(2) |
|
||||
| Kurulum → `Ön kontrol (--check)` | Değişiklik yok, rapor üretir | LAB(2) |
|
||||
| Kurulum → `Bu cihazı kur`, bayi no `12010193`, `--offline` | `PROVISIONED_OFFLINE`; ana makine adı `bf-12010193`; ağ erişimi olmadan tamamlanır | LAB(2) |
|
||||
| Geçersiz bayi no (7/9 hane, harf) | Kırmızı uyarı; `Komutu göster ve çalıştır` hata penceresi açar, komut üretilmez | LAB(2) |
|
||||
| Cihaz işlemleri → `Kontrollü yeniden başlatma`, tek cihaz | İki onay istenir; cihaz yeniden başlar; denetim satırı yazılır | LAB(2) |
|
||||
| Wave-scoped playbook, hedef `Tüm filo (dikkat)` | Dalga dalga; her dalga ayrı onaylanır; hata sonraki dalgayı durdurur | LAB(2) |
|
||||
| `sudo admin/bf-bootstrap.sh` iki kez koşulur | İkinci koşu hata üretmez (idempotent), araçlar yerinde | LAB(2) |
|
||||
| `sudo bf-menu --list` / `--list-targets` | İşlem kataloğu ve envanter hedefleri hatasız listelenir | LAB(2) |
|
||||
| `sudo bf-menu` açılır, `q` ile çıkılır | Konsol hiçbir değişiklik yapmaz | LAB(2) |
|
||||
| Kategori 1 → 1 kuru koşu (`--check`) | Değişiklik yok, rapor üretir | LAB(2) |
|
||||
| Kategori 1 → 2 kurulum, bayi no `12010193` | `PROVISIONED_OFFLINE`; hostname `bf-12010193` | LAB(2) |
|
||||
| Geçersiz bayi no (7/9 hane, harf) | Konsol kurulumu başlatmaz | LAB(2) |
|
||||
| Kategori 2 → 2 → 9 reboot, tek cihaz | Onay istenir; cihaz yeniden başlar; log satırı yazılır | LAB(2) |
|
||||
| Kategori 2 wave-scoped playbook, hedef "all" | Dalga dalga; her dalga ayrı onaylanır; hata sonraki dalgayı durdurur | LAB(2) |
|
||||
| production dalgası denemesi | `production` yazılmadan çalışmaz | LAB(2) |
|
||||
| Araçlar → `Konsol denetim günlüğü` | Mod `600`; secret ve ham komut çıktısı yok | LAB(2) |
|
||||
| Yetkisiz oturum: `bf --dry-run` ile yazma işlemi planla, sonra çalıştırmayı dene | Başlıkta uyarı şeridi; `[ENGELLENDİ]` satırı; hiçbir komut çalışmaz; çıkış kodu 2 | LAB(2) |
|
||||
| Kategori 4 → 11 konsol log'u | Mod `600`; secret ve ham playbook çıktısı yok | LAB(2) |
|
||||
| `sudo bf-creds` (bayraksız) | Hiçbir parola üretilmez, açıkça söyler | LAB(2) |
|
||||
| `sudo bf-creds --generate` | Kayıt dosyası `0600`; parola ekranda görünmez | LAB(2) |
|
||||
|
||||
## 11. Rollback
|
||||
|
||||
1. Kurulum yarıda kaldıysa: `Kurulum` sekmesi → `Başarısız kuruluma devam et (--resume)`; modüller idempotenttir ve zaten `OK` olanlar atlanır.
|
||||
2. Yanlış bayi no girildiyse: doğru no ile tam yeniden koşu; kimlik modülü ana makine adını üzerine yazar (K-12).
|
||||
3. Bootstrap yanlış kurulduysa: repoyu güncelleyip (`Araçlar` → `Bu kopyayı güncelle`, `git pull --ff-only`) yeniden koş; bootstrap **hiçbir şeyi silmez, `git reset`/`stash` yapmaz**, yerel çalışmanı korur.
|
||||
4. Filo işlemi başarısız dalga bıraktıysa: `Onaylı paket güncellemesi kur` geri alma zinciri önceki onaylı release manifestine döner (10, 30).
|
||||
5. Grafik arayüz bozulduysa/başlatılamıyorsa: iş emri durdurmaz — `sudo bf --tui` ile aynı iş mantığına devam edilir; Python'un kendisi de yoksa yedek bash konsolu `sudo bf-menu` kullanılır.
|
||||
6. Çözülmeyen cihaz: 17-RECOVERY seviye merdiveni (L8 = temiz yeniden kurulum) uygulanır.
|
||||
1. Kurulum yarıda kaldıysa: kategori **1 → 3 "Resume after a failed run"** (`--resume`); modüller idempotenttir.
|
||||
2. Yanlış bayi no girildiyse: doğru no ile tam yeniden koşu; kimlik modülü hostname'i üzerine yazar (K-12).
|
||||
3. Bootstrap yanlış kurulduysa: repoyu güncelleyip (`git pull --ff-only`) yeniden koş; bootstrap **hiçbir şeyi silmez, `git reset`/`stash` yapmaz**, yerel çalışmanı korur.
|
||||
4. Filo işlemi başarısız dalga bıraktıysa: "Deploy approved package update" geri alma zinciri önceki onaylı release manifestine döner (10, 30).
|
||||
5. Çözülmeyen cihaz: 17-RECOVERY seviye merdiveni (L8 = temiz yeniden kurulum) uygulanır.
|
||||
|
||||
## 12. Kontrol Listesi
|
||||
|
||||
- [x] `bfos` paketi ve giriş dosyası `admin/bf` repoda mevcut; `sudo bf` grafik arayüzü açar, `sudo bf --tui` terminal konsolu.
|
||||
- [x] `admin/bf-bootstrap.sh` `/usr/local/bin/bf` bağını kurar; bash konsolu (`admin/bf-menu`) yedek olarak korunur, ana yol değildir.
|
||||
- [x] Kurulum git tabanlı (clone + bootstrap); kurulum paketleri depoda (1321 `.deb`, Git LFS) — kuran kişi hiçbir şey indirmez.
|
||||
- [x] `python3-tk` çevrimdışı depoda pinli; kurulum sonu kapısı tkinter'ı denetler ve eksikse WARN + `--tui` yolu bildirir.
|
||||
- [x] Her komut çalıştırılmadan önce gösterilip onaylanıyor; yıkıcı işlemler iki kez soruyor; onay sonrası komut değişirse kesin komut yeniden onaylatılıyor.
|
||||
- [x] Bayi no kapısı `^[0-9]{8}$`; geçersiz girişte komut üretilmiyor.
|
||||
- [x] Filo işlemleri açık hedefle; wave-scoped filo akışı dalga dalga ilerliyor; production için `production` yazma zorunlu.
|
||||
- [x] Katalog, playbook kapsamıyla uyuşmazsa çalıştırmayı reddediyor (kapsam playbook dosyasından okunur).
|
||||
- [x] Yetki modeli: `sudo bf` tam yetki; yetkisiz açılışta yazma işlemleri kapalı ve çalıştırma katmanı `[ENGELLENDİ]` ile reddediyor.
|
||||
- [x] Grafik ekran/tkinter yokluğunda Türkçe hata + `sudo bf --tui` önerisi ve çıkış kodu 3.
|
||||
- [x] `admin/bf-bootstrap.sh`, `admin/bf-menu` ve `admin/bf-creds` repoda mevcut; `sudo bf-menu` tek giriş noktası.
|
||||
- [x] Kurulum git tabanlı (clone + bootstrap); ISO yolu ikincil/opsiyonel olarak korunuyor (26 silinmedi).
|
||||
- [x] Her komut çalıştırılmadan önce gösterilip onaylanıyor; yıkıcı işlemler iki kez soruyor.
|
||||
- [x] Bayi no kapısı `^[0-9]{8}$`; geçersiz girişte kurulum başlamıyor.
|
||||
- [x] Filo işlemleri açık `--limit` ile; wave-scoped `all` dalga dalga ilerliyor; production için `production` yazma zorunlu.
|
||||
- [x] Konsol, playbook kapsamıyla uyuşmazsa çalıştırmayı reddediyor.
|
||||
- [x] Şifre üretimi varsayılan **kapalı**; yalnız `bf-creds --generate` ile üretiliyor; parola ekrana/loga gitmiyor.
|
||||
- [x] `Cihaz işlemleri` içinde onaysız güncelleme seçeneği **yok**; `Bekleyen güvenlik güncellemeleri` yalnız rapor.
|
||||
- [x] Denetim kaydı mod `600`; secret ve ham komut çıktısı yazılmıyor.
|
||||
- [ ] Örnek pencere/çıktı satırları gerçek LAB koşusuyla (özellikle kurulum betiğinin `[installer]` satırları) güncellendi.
|
||||
- [x] Kategori 2'de onaysız güncelleme seçeneği **yok**; "Pending security updates" yalnız rapor.
|
||||
- [x] Denetim log'u mod `600`; secret ve ham playbook çıktısı yazılmıyor.
|
||||
- [ ] Örnek ekran çıktıları gerçek LAB çıktısıyla değiştirildi.
|
||||
|
||||
## 13. Açık Sorular
|
||||
|
||||
- [ ] Katalog işlemlerinin playbook kümesiyle tam eşleşmesi: yeni playbook'lar kataloğa nasıl eklenecek (`bfos/operations.py` + sekme tablosu) ve bu süreç hangi PR şablonuyla yürüyecek (sahibi: 09 + arayüz sahibi).
|
||||
- [ ] Terminal konsolunda bulunup grafik katalogda ayrı işlem olmayan araçlar (ortam bilgisi, canlı donanım kontrolü, uzak erişim durumu, donanım envanteri, merkez uç noktası probu) sekme listesine taşınacak mı; iki giriş noktası bu noktada bilinçli olarak ayrı mı kalacak (sahibi: arayüz sahibi + 15).
|
||||
- [ ] Merkez hazırlığı ekranlarının gerçek merkez uç noktaları geldiğinde hangi kanıtı "hazır" sayacağı (sahibi: 29/21 yazarları).
|
||||
- [ ] Konsol işlem kataloğunun playbook kümesiyle tam eşleşmesi: `bf-service-restart`/`bf-run-script` gibi yeni playbook'lar kataloğa nasıl eklenecek (süreç/PR şablonu) (sahibi: 09 + konsol sahibi).
|
||||
- [ ] Merkez hazırlığı ekranlarının (kategori 3) gerçek merkez endpoint'leri geldiğinde hangi kanıtı "hazır" sayacağı (sahibi: 29/21 yazarları).
|
||||
- [ ] `bf-creds --fetch` hedefinin (`admin/secrets/`) kurumsal kasa (vault) akışına bağlanması (sahibi: 06-ssh + merkezi admin).
|
||||
- [ ] Arayüz işlem geçmişinin merkezi log toplamaya (Loki/ELK, Faz-sonrası) dahil edilip edilmeyeceği (sahibi: 15-LOGGING yazarı).
|
||||
- [ ] Konsol işlem geçmişinin merkezi log toplamaya (Loki/ELK, Faz-sonrası) dahil edilip edilmeyeceği (sahibi: 15-LOGGING yazarı).
|
||||
- [ ] Git kurulumu ile ISO/firstboot yolunun uzun vadeli rolü: ISO tamamen arşiv mi, yedek yol mu kalır (sahibi: yönetim + 26 yazarı).
|
||||
- [ ] Kurumsal proxy/air-gapped sahalarda `git clone` yerine iç ayna (mirror) deposu kullanılacak mı; bootstrap `--repo`/`BF_REPO_URL` ile buna hazır mı (sahibi: merkezi admin).
|
||||
- [ ] Grafik arayüzün uzak masaüstü (xRDP) oturumu üzerinden de çalıştırılması desteklenen/desteklenmeyen bir senaryo mu; K-22 ile ilişkisi (sahibi: 08-rdp + arayüz sahibi).
|
||||
|
||||
---
|
||||
|
||||
## Ek: Arayüz haritası
|
||||
## Ek: Menü haritası
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
START["sudo bf<br/>(grafik arayüz, varsayılan)"] --> WIN["Pencere: Blueforce Field OS — Yönetim<br/>üst çubuk: Bayi no (8 hane) + Dalga + Tüm filo"]
|
||||
WIN --> SIMPLE["Basit mod (varsayılan)<br/>3 büyük düğme: Kur / Durum / Çıkış"]
|
||||
WIN -->|"üstte 'Detaylı mod'"| DETAIL["Detaylı mod<br/>5 kategori sekmesi"]
|
||||
SIMPLE -. "Detaylı mod düğmesi" .-> DETAIL
|
||||
DETAIL --> T1["Kurulum (6 işlem, 3 yazma)<br/>ön kontrol / bu cihazı kur / resume / --only<br/>modül durumu / kurulum günlüğü"]
|
||||
DETAIL --> T2["Cihaz işlemleri (21 işlem, 9 yazma)<br/>11 salt-okunur rapor + 10 bakım işlemi"]
|
||||
DETAIL --> T3["Merkez hazırlığı (4, hepsi salt-okunur)<br/>envanter / PLACEHOLDER / uç noktalar / kontrol listesi"]
|
||||
DETAIL --> T4["Araçlar (9 işlem, 1 yazma)<br/>checkout güncelle / katalog / kapılar / destek paketi / denetim kaydı"]
|
||||
DETAIL --> T5["Cihaz bilgisi (8, hepsi salt-okunur)<br/>özet / kimlik / ağ / kaynaklar / paketler / servisler / journal / state"]
|
||||
WIN --> FOOT["Alt çubuk: Komutu göster ve çalıştır / Çıktıyı temizle /<br/>Çalışanı iptal et / Yalnız denetim (--check) / Çıkış"]
|
||||
FOOT --> GATES{"Onaylar: komut önizleme →<br/>dalga adı / production / GATE / all →<br/>yıkıcı ikinci onay"}
|
||||
GATES --> RUN["Komut çıktı alanına yazılır ve koşar<br/>denetim kaydı: /var/log/blueforce-console.log (600)"]
|
||||
START -. "grafik ekran veya tkinter yoksa<br/>(çıkış kodu 3, Türkçe hata)" .-> TUI["sudo bf --tui<br/>(terminal konsolu, yedek)"]
|
||||
TUI -. "python3 yoksa" .-> BASH["admin/bf-menu<br/>(bash konsolu, son çare)"]
|
||||
START["sudo bf-menu"] --> MAIN{"Ana menü — kategori seç<br/>q = çıkış"}
|
||||
MAIN --> C1["1) Installation<br/>bu cihazı kurar (filo cihazına dokunmaz)"]
|
||||
MAIN --> C2["2) Device operations<br/>mevcut playbook'lar + açık hedef"]
|
||||
MAIN --> C3["3) Central (preparation)<br/>merkez entegrasyonunu denetle/hazırla"]
|
||||
MAIN --> C4["4) Tools<br/>repo + yerel yardımcılar"]
|
||||
MAIN --> C5["5) Device information<br/>salt-okunur bilgi ekranları"]
|
||||
C1 --> I1["1 Kuru koşu --check<br/>2 Kurulum (bayi no)<br/>3 Devam --resume<br/>4 Tek modül --only<br/>5 Modül durumu / 6 Log"]
|
||||
C2 --> P1["2.1 Salt-okunur raporlar (11)"]
|
||||
C2 --> P2["2.2 Bakım işlemleri (10, yıkıcı onaylı)"]
|
||||
C2 --> P3["2.3 Envanter hedefleri"]
|
||||
C3 --> K1["Hazırlık raporu / endpoint'ler / probe<br/>dalga kapı durumu / kontrol listesi"]
|
||||
C4 --> T1["Checkout güncelle / ortam bilgisi / katalog<br/>gate'ler / bf-release / destek paketi / log"]
|
||||
C5 --> D1["Kimlik / sağlık / durum / ağ / disk<br/>paketler / servisler / journal / envanter"]
|
||||
```
|
||||
|
||||
## Ek: İlk kurulum ve durum akışı
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
G["git clone<br/>Blueforce-Linux"] --> LFS["git lfs pull<br/>provisioning/offline-repo/packages/<br/>1321 .deb"]
|
||||
LFS --> B["sudo admin/bf-bootstrap.sh<br/>(veya curl | sudo bash)"]
|
||||
B --> BF["/usr/local/bin/bf<br/>+ bf-menu (yedek)"]
|
||||
BF --> GUI["sudo bf<br/>grafik arayüz"]
|
||||
GUI --> ID["Üst çubuk: bayi no gir<br/>ör. 12010193"]
|
||||
ID --> INST["Kurulum sekmesi → Bu cihazı kur<br/>--offline (yerel paket deposu)"]
|
||||
INST --> MOD["18/18 modül OK<br/>+ final-check: tkinter kapısı"]
|
||||
MOD --> PO["PROVISIONED_OFFLINE<br/>yerel kurulum bitti"]
|
||||
PO -->|"Cihaz bilgisi: kayıt durumu"| EN["ENROLLED"]
|
||||
G["git clone<br/>Blueforce-Linux"] --> B["sudo admin/bf-bootstrap.sh<br/>(veya curl | sudo bash)"]
|
||||
B --> M["sudo bf-menu"]
|
||||
M --> ID["Kategori 1: bayi no gir<br/>ör. 12010193"]
|
||||
ID --> INST["18/18 modül OK"]
|
||||
INST --> PO["PROVISIONED_OFFLINE<br/>yerel kurulum bitti"]
|
||||
PO -->|kategori 5: enrollment| EN["ENROLLED"]
|
||||
EN -->|merkez kanal kanıtı| RDY["READY<br/>teslim edilebilir"]
|
||||
GUI -. "grafik ekran yok / tkinter yok" .-> TUI["sudo bf --tui"]
|
||||
B -. "ISO/firstboot yolu<br/>(ikincil, opsiyonel)" .-> FB["docs/26 / docs/27"]
|
||||
```
|
||||
|
||||
## Ek: Hızlı referans (arayüz ↔ komut)
|
||||
## Ek: Hızlı referans (menü ↔ komut)
|
||||
|
||||
Her satırda önce **arayüzdeki yol**, sonra aynı işin **`sudo bf --tui` (terminal konsolu)** karşılığı, en altta altta çalışan komut/playbook yazar.
|
||||
|
||||
| Arayüzde (grafik) | `sudo bf --tui` karşılığı | Altında çalışan komut / playbook |
|
||||
|---|---|---|
|
||||
| Basit mod → `Kur` → `Ön kontrol (--check)` | `1) Kur` → `1) Ön kontrol (--check)` | `blueforce-install.sh --dealer-id <8hane> --check` |
|
||||
| Basit mod → `Kur` → `Kurulumu başlat` | `1) Kur` → `2) Bu cihazı kur` | `blueforce-install.sh --dealer-id <8hane>` (`--offline`, `--resume` opsiyonel) |
|
||||
| Kurulum → `Başarısız kuruluma devam et` | Kurulum → `3) Başarısız kurulumu sürdür` | `blueforce-install.sh --dealer-id <8hane> --resume` |
|
||||
| Kurulum → `Tek modül çalıştır (--only)` | Kurulum → `4) Tek modül çalıştır` | `blueforce-install.sh --dealer-id <8hane> --only <modül>` |
|
||||
| Kurulum → `Kurulum modül durumu` / `Kurulum günlüğü` | Kurulum → `5)` / `6)` | `/var/lib/blueforce/install-state`, `/var/log/blueforce-install.log` |
|
||||
| Basit mod → `Durum` / Cihaz bilgisi → `Durum özeti` | `1) Kur` menüsünden `2) Durum` / Cihaz bilgisi → `2) Sağlık özeti` | `bf-status`, `state.json` beyaz listesi, envanter hedefleri |
|
||||
| Cihaz işlemleri → `Erişilebilirlik testi (ping)` | Cihaz işlemleri → `1) Salt okunur raporlar` → ping | `bf-ping.yml` |
|
||||
| Cihaz işlemleri → `Field OS sürüm raporu` | Cihaz işlemleri → salt-okunur raporlar → Field OS sürümü | `bf-fieldos-version.yml` |
|
||||
| Cihaz işlemleri → `Log topla / destek paketi` | Cihaz işlemleri → `2) Bakım işlemleri` → log topla | `bf-collect-logs.yml` |
|
||||
| Cihaz işlemleri → `Kontrollü yeniden başlatma` | Cihaz işlemleri → bakım işlemleri → kontrollü reboot | `bf-reboot.yml` (sürüm kapılı, sıralı + sağlık kapısı) |
|
||||
| Cihaz işlemleri → `Onaylı paket güncellemesi kur` | Cihaz işlemleri → bakım işlemleri → onaylı güncelleme | `bf-deploy-update.yml` (`paket=sürüm` pinleri) |
|
||||
| Cihaz işlemleri → `Grafik arayüzü kapat/aç` | Cihaz işlemleri → bakım işlemleri → GUI off / on | `bf-gui-off.yml` / `bf-gui-on.yml` (xRDP'e dokunmaz, K-22) |
|
||||
| Merkez hazırlığı → `Envanter hedefleri` | Merkez hazırlığı → `1..5` ekranları | envanter okuma + `group_vars/all.yml` denetimi + DNS/TCP probe (`--tui`) |
|
||||
| Araçlar → `Bu kopyayı güncelle` | Araçlar → `1) Depoyu güncelle` | `git -C <repo> pull --ff-only` |
|
||||
| Araçlar → `İşlem kataloğunu göster` | Araçlar → `3) İşlem kataloğunu göster` | `bf --list` (48 işlem, kategori kategori) |
|
||||
| Araçlar → `Yerel çevrimdışı kapısı` / `Kayıt kapısı` / `Teslim kapısı` | Araçlar → `4)`, `5)`, `6)` | `bf-check-local`, `bf-check-enrollment`, `bf-check-ready` (`--check`) |
|
||||
| Araçlar → `Derin teşhis` / `Field OS sürüm kimliği` | Araçlar → `7)`, `10)` | `bf-diagnostics` (yoksa `bf-status`), `bf-release` |
|
||||
| Araçlar → `Destek paketi oluştur` | Araçlar → `12) Destek paketi` | `bf-support-bundle --out-dir /var/tmp` |
|
||||
| Araçlar → `Konsol denetim günlüğü` | Araçlar → `13) Konsol denetim kaydını göster` | `tail -n 40 /var/log/blueforce-console.log` |
|
||||
| Cihaz bilgisi → `Kimlik` / `Ağ` / `Disk, bellek, yük` / `Servis durumu` / `Son journal hataları` | Cihaz bilgisi → `1)`, `4)`, `5)`, `7)`, `8)` | `hostname` + `state.json`, `ip`/`resolv.conf`/`wg show`, `df`-`free`-`uptime`, `systemctl is-active`, `journalctl -p err -n 20` |
|
||||
| Cihaz bilgisi → `Kurulum/kayıt durumu` | Cihaz bilgisi → `3) Kurulum ve kayıt durumu` | `state.json` beyaz liste (`phase`, `enrollment_status`, `fleet_status`, `device_id`, `provisioning_id`) |
|
||||
| (arayüzde ayrı işlem değil) | Araçlar → `2) Ortam ve sürüm bilgisi`, `8) Canlı donanım / OS kontrolü`, `9) Uzak erişim kanalları`, `11) Donanım envanteri` | `environment_lines`, `bf-live-hw-check`, `bf-remote-status --check`, `bf-hardware-inventory.sh` |
|
||||
| Arayüz dışı (opsiyonel) | Arayüz dışı (opsiyonel) | `sudo bf-creds --generate` / `--fetch` |
|
||||
| Denetim kaydı | Denetim kaydı | `/var/log/blueforce-console.log` (mod `600`; yazılamazsa `$XDG_STATE_HOME/blueforce/blueforce-console.log`) |
|
||||
| Grafik ekran/tkinter yoksa | Bu konsol | `sudo bf --tui`; Python yoksa `sudo bf-menu` |
|
||||
| Menüde | Altında çalışan komut / playbook |
|
||||
|---|---|
|
||||
| 1 → 1 Kuru koşu | `blueforce-install.sh --dealer-id <8hane> --check` |
|
||||
| 1 → 2 Kurulum | `blueforce-install.sh --dealer-id <8hane>` (`--offline`, `--resume` opsiyonel) |
|
||||
| 1 → 4 Tek modül | `blueforce-install.sh --dealer-id <8hane> --only <modül>` |
|
||||
| 1 → 5 / 6 Modül durumu / log | `/var/lib/blueforce/install-state`, `/var/log/blueforce-install.log` |
|
||||
| 2.1 → 1 Ping | `bf-ping.yml` |
|
||||
| 2.1 → 9 Field OS sürümü | `bf-fieldos-version.yml` |
|
||||
| 2.2 → 7 Log topla | `bf-collect-logs.yml` |
|
||||
| 2.2 → 9 Kontrollü reboot | `bf-reboot.yml` (release-gated, seri + sağlık kapısı) |
|
||||
| 2.2 → 10 Onaylı güncelleme | `bf-deploy-update.yml` (`package=version` pinleri) |
|
||||
| 3 → 1..5 Merkez hazırlığı | `ansible/inventory/group_vars/all.yml` denetimi + DNS/TCP probe |
|
||||
| 4 → 4/5/6 Kapılar | `bf-check-local`, `bf-check-enrollment`, `bf-check-ready` |
|
||||
| 4 → 8 Sürüm kimliği | `bf-release` |
|
||||
| 4 → 10 Destek paketi | `bf-support-bundle --out-dir` |
|
||||
| 5 → 2/3 Sağlık ve durum | `bf-status`, `/var/lib/blueforce/state.json`, `bf-enrollment-status` |
|
||||
| Konsol dışı (opsiyonel) | `sudo bf-creds --generate` / `--fetch` |
|
||||
| Denetim log'u | `/var/log/blueforce-console.log` (mod `600`) |
|
||||
|
|
|
|||
|
|
@ -146,15 +146,9 @@ inspect_deb() {
|
|||
printf ' dpkg-deb çıktısı: %s\n' "$raw" >&2
|
||||
return 1
|
||||
fi
|
||||
# Only the value of each field belongs in these variables: dpkg-deb prints
|
||||
# "<Field>: <value>" when several fields are asked for, and a bare value when
|
||||
# one is. Strip a leading "<word>: " only if it is present: always stripping
|
||||
# emptied the single-field reads, never stripping left "Package: curl" as a
|
||||
# package name. A version cannot start with a letter-and-colon ("1:2.3" is
|
||||
# fine), so the pattern is safe.
|
||||
DEB_PKG="$(printf '%s\n' "$raw" | sed -n '1p' | awk '{ if ($1 ~ /:$/) { $1=""; sub(/^ /, "") } print }')"
|
||||
DEB_VER="$(printf '%s\n' "$raw" | sed -n '2p' | awk '{ if ($1 ~ /:$/) { $1=""; sub(/^ /, "") } print }')"
|
||||
DEB_ARCH="$(printf '%s\n' "$raw" | sed -n '3p' | awk '{ if ($1 ~ /:$/) { $1=""; sub(/^ /, "") } print }')"
|
||||
DEB_PKG="$(printf '%s\n' "$raw" | sed -n '1p')"
|
||||
DEB_VER="$(printf '%s\n' "$raw" | sed -n '2p')"
|
||||
DEB_ARCH="$(printf '%s\n' "$raw" | sed -n '3p')"
|
||||
|
||||
if [[ ! "$DEB_PKG" =~ $PACKAGE_NAME_RE ]]; then
|
||||
printf 'HATA: paket adı geçersiz: "%s" (%s)\n' "$DEB_PKG" "$file" >&2
|
||||
|
|
@ -181,12 +175,8 @@ scan_existing() {
|
|||
[[ -d "$PACKAGES_DIR" ]] || return 0
|
||||
while IFS= read -r -d '' deb; do
|
||||
sha="$(file_sha256 "$deb")"
|
||||
# A single requested field comes back bare ("curl"), so strip a label only
|
||||
# when dpkg-deb actually printed one. Always stripping emptied these keys,
|
||||
# which made a labelled/empty entry never match the incoming candidate: a
|
||||
# version conflict went undetected and the same package was copied twice.
|
||||
pkg="$(dpkg-deb -f "$deb" Package 2>/dev/null | awk '{ if ($1 ~ /:$/) { $1=""; sub(/^ /, "") } print }' || true)"
|
||||
ver="$(dpkg-deb -f "$deb" Version 2>/dev/null | awk '{ if ($1 ~ /:$/) { $1=""; sub(/^ /, "") } print }' || true)"
|
||||
pkg="$(dpkg-deb -f "$deb" Package 2>/dev/null || true)"
|
||||
ver="$(dpkg-deb -f "$deb" Version 2>/dev/null || true)"
|
||||
if [[ -z "$pkg" || -z "$ver" ]]; then
|
||||
printf 'UYARI: packages/ içindeki okunamayan dosya yok sayıldı: %s\n' "${deb##*/}" >&2
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -52,10 +52,7 @@ LOCK_HEADER="$(printf 'package\tversion\tarchitecture\tsha256\tsource')"
|
|||
UNPINNED='UNPINNED'
|
||||
SCHEMA_VERSION=1
|
||||
# Entries an output directory may hold without being treated as foreign.
|
||||
# repo-manifest.yaml belongs here: this script writes it into the bundle after
|
||||
# the index, so a rebuild would otherwise refuse its own previous output as a
|
||||
# stranger and stop ("bu depoya ait olmayan dosya") on every second run.
|
||||
ALLOWED_ENTRIES='pool Packages Packages.gz packages.lock.tsv SHA256SUMS repo-manifest.yaml .gitkeep'
|
||||
ALLOWED_ENTRIES='pool Packages Packages.gz packages.lock.tsv SHA256SUMS .gitkeep'
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
|
|
@ -287,20 +284,10 @@ fi
|
|||
|
||||
while IFS= read -r -d '' deb; do
|
||||
base="$(basename "$deb")"
|
||||
# dpkg-deb prints "<Field>: <value>"; only the value belongs in the pool key,
|
||||
# so strip the label. Taking the whole line made every package fail the name
|
||||
# check and the pool came out empty -- a stub dpkg-deb in the test suite hides
|
||||
# this, so it only surfaces against real .deb files.
|
||||
raw="$(dpkg-deb -f "$deb" Package Version Architecture 2>/dev/null || true)"
|
||||
# dpkg-deb prints a bare value for a single requested field but
|
||||
# "<Field>: <value>" for several. Both shapes have to survive the read: the
|
||||
# awk expression drops the label only when the first word ends with a colon,
|
||||
# and sed -n 's/.../p' (used here first) printed nothing at all when the
|
||||
# pattern did not match, which emptied every row. A version may contain a
|
||||
# colon ("1:2.3") but never starts with a word-and-colon, so this is safe.
|
||||
package="$(printf '%s\n' "$raw" | sed -n '1p' | awk '{ if ($1 ~ /:$/) { $1=""; sub(/^ /, "") } print }')"
|
||||
version="$(printf '%s\n' "$raw" | sed -n '2p' | awk '{ if ($1 ~ /:$/) { $1=""; sub(/^ /, "") } print }')"
|
||||
arch="$(printf '%s\n' "$raw" | sed -n '3p' | awk '{ if ($1 ~ /:$/) { $1=""; sub(/^ /, "") } print }')"
|
||||
package="$(printf '%s\n' "$raw" | sed -n '1p')"
|
||||
version="$(printf '%s\n' "$raw" | sed -n '2p')"
|
||||
arch="$(printf '%s\n' "$raw" | sed -n '3p')"
|
||||
if [[ ! "$package" =~ $PACKAGE_NAME_RE || -z "$version" ]]; then
|
||||
POOL_ERRORS+=("$base: geçerli bir Debian paketi okunamadı; add-packages.sh ile ekleyin")
|
||||
continue
|
||||
|
|
@ -460,11 +447,6 @@ else
|
|||
rm -rf "$OUTPUT"
|
||||
mv -- "$STAGE" "$OUTPUT"
|
||||
STAGE=''
|
||||
# mktemp -d creates 0700, and this directory is delivered: the installer reads
|
||||
# the bundle, an operator inspects it, and a build host may copy it as another
|
||||
# user. A private mode makes a valid bundle look missing (the installer's
|
||||
# readability probe sees an unreadable directory), so publish it explicitly.
|
||||
chmod 0755 "$OUTPUT"
|
||||
printf 'OK: depo yazıldı: %s\n' "$(rel_to_repo "$OUTPUT")"
|
||||
fi
|
||||
|
||||
|
|
@ -558,8 +540,8 @@ printf ' git add -f %s\n' "$(rel_to_repo "$OUTPUT")"
|
|||
printf ' git add %s\n' "$(rel_to_repo "$MANIFEST_OUT")"
|
||||
printf ' git commit -m "offline repo: %d paket, offline APT indeksi"\n' "$POOL_TOTAL"
|
||||
if [[ ! -d "$SCRIPT_DIR/build" ]]; then
|
||||
printf '\nNOT: provisioning/iso/build-blueforce-iso.sh varsayılan olarak bu dizini ("built/") arar.\n'
|
||||
printf ' Eski "build/" adı yalnız uyarıyla kabul edilir; bu çıktı ISO ile uyumludur.\n'
|
||||
printf '\nNOT: provisioning/iso/build-blueforce-iso.sh offline depoyu "build" adıyla arıyor.\n'
|
||||
printf ' ISO ile aynı yolu kullanmak isterseniz: ./build-index.sh --output build\n'
|
||||
fi
|
||||
printf '\nDoğrulama (hedef cihazda /opt/blueforce/offline-repo):\n'
|
||||
printf ' cd /opt/blueforce/offline-repo && sha256sum -c SHA256SUMS\n'
|
||||
|
|
|
|||
|
|
@ -249,11 +249,7 @@ for list in "$SCRIPT_DIR/manifests/base-packages.txt" "$SCRIPT_DIR/manifests/rem
|
|||
pins=$((pins + 1))
|
||||
found=0
|
||||
for deb in "${debs[@]}"; do
|
||||
# A single requested field comes back bare, so strip a label only when
|
||||
# dpkg-deb printed one; always stripping emptied both halves and no pin
|
||||
# could ever match.
|
||||
deb_pin="$(dpkg-deb -f "$deb" Package | awk '{ if ($1 ~ /:$/) { $1=""; sub(/^ /, "") } print }')=$(dpkg-deb -f "$deb" Version | awk '{ if ($1 ~ /:$/) { $1=""; sub(/^ /, "") } print }')"
|
||||
[[ "$deb_pin" == "$pin" ]] && found=1 && break
|
||||
[[ "$(dpkg-deb -f "$deb" Package)=$(dpkg-deb -f "$deb" Version)" == "$pin" ]] && found=1 && break
|
||||
done
|
||||
[[ "$found" -eq 1 ]] || { printf 'Pinned package not supplied locally: %s\n' "$pin" >&2; exit 1; }
|
||||
done < "$list"
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
|
@ -1,3 +0,0 @@
|
|||
e608222b648a07f0223e0dde07b62f3e67e52620de5ee7ab786fc23093fe7cac Packages
|
||||
9253dabe3c6e547176acebec84512024b392f55f5f556fb8b523f7553e8341c0 Packages.gz
|
||||
d2846fefb7961ebed6a8156fa6a4c1abcc6b5d5aa4f9ba4afad01915b50a905d packages.lock.tsv
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -41,23 +41,6 @@ smartmontools=7.5-2
|
|||
ufw=0.36.2-9build1
|
||||
iptables=1.8.11-2ubuntu3
|
||||
|
||||
# --- operator GUI (bfos/ui_gui.py; module 18-final-check.sh) ---
|
||||
# tkinter ships as its own package on Ubuntu, so a minimal image has Python but
|
||||
# no GUI. Without it the operator application cannot open its window at all --
|
||||
# and the fleet has no network to fetch it from.
|
||||
python3-tk=3.14.3-0ubuntu2
|
||||
# python3-tk's own dependency closure. Pinned explicitly because the installer
|
||||
# resolves nothing from a remote source: whatever the pin does not name must
|
||||
# already be on the image.
|
||||
python3.14-tk=3.14.4-1ubuntu0.2
|
||||
libtk8.6=8.6.17-1build1
|
||||
libreadline8t64=8.3-4
|
||||
readline-common=8.3-4
|
||||
libffi8=3.5.2-4
|
||||
libsqlite3-0=3.46.1-9ubuntu0.2
|
||||
libbrotli1=1.2.0-3build1
|
||||
openssl=3.5.5-1ubuntu3.5
|
||||
|
||||
# --- monitoring (module 12-monitoring.sh) ---
|
||||
# The textfile collector ships inside this package; no extra dependency is needed.
|
||||
prometheus-node-exporter=1.10.2-1
|
||||
|
|
|
|||
|
|
@ -22,15 +22,6 @@ base-packages.txt smartmontools scripts/diagnostics/bf-diagnostics SMART disk he
|
|||
base-packages.txt ufw scripts/install/installer/modules/13-firewall.sh host firewall baseline
|
||||
base-packages.txt iptables scripts/install/installer/modules/13-firewall.sh rule backends used by the firewall module
|
||||
base-packages.txt prometheus-node-exporter scripts/install/installer/modules/12-monitoring.sh node exporter including the textfile collector
|
||||
base-packages.txt python3-tk scripts/install/installer/modules/18-final-check.sh tkinter is a separate package on Ubuntu; without it the operator GUI cannot start
|
||||
base-packages.txt python3.14-tk scripts/install/installer/modules/18-final-check.sh python3-tk dependency closure; the installer resolves nothing from a remote source
|
||||
base-packages.txt libtk8.6 scripts/install/installer/modules/18-final-check.sh python3-tk dependency closure; the installer resolves nothing from a remote source
|
||||
base-packages.txt libreadline8t64 scripts/install/installer/modules/18-final-check.sh python3-tk dependency closure; the installer resolves nothing from a remote source
|
||||
base-packages.txt readline-common scripts/install/installer/modules/18-final-check.sh python3-tk dependency closure; the installer resolves nothing from a remote source
|
||||
base-packages.txt libffi8 scripts/install/installer/modules/18-final-check.sh python3-tk dependency closure; the installer resolves nothing from a remote source
|
||||
base-packages.txt libsqlite3-0 scripts/install/installer/modules/18-final-check.sh python3-tk dependency closure; the installer resolves nothing from a remote source
|
||||
base-packages.txt libbrotli1 scripts/install/installer/modules/18-final-check.sh python3-tk dependency closure; the installer resolves nothing from a remote source
|
||||
base-packages.txt openssl scripts/install/installer/modules/18-final-check.sh python3-tk dependency closure; the installer resolves nothing from a remote source
|
||||
remote-access.txt rustdesk scripts/install/installer/modules/09-rustdesk.sh pinned vendor .deb; not in the Ubuntu archive
|
||||
remote-access.txt libxdo3 scripts/install/installer/modules/09-rustdesk.sh rustdesk 1.4.9 Depends; pulled explicitly because the vendor .deb is installed with dpkg, not from an APT source
|
||||
remote-access.txt libva-x11-2 scripts/install/installer/modules/09-rustdesk.sh rustdesk 1.4.9 Depends; pulled explicitly because the vendor .deb is installed with dpkg, not from an APT source
|
||||
|
|
|
|||
|
Can't render this file because it has a wrong number of fields in line 13.
|
BIN
provisioning/offline-repo/packages/libbrotli1_1.2.0-3build1_amd64.deb
(Stored with Git LFS)
BIN
provisioning/offline-repo/packages/libbrotli1_1.2.0-3build1_amd64.deb
(Stored with Git LFS)
Binary file not shown.
BIN
provisioning/offline-repo/packages/libffi8_3.5.2-4_amd64.deb
(Stored with Git LFS)
BIN
provisioning/offline-repo/packages/libffi8_3.5.2-4_amd64.deb
(Stored with Git LFS)
Binary file not shown.
BIN
provisioning/offline-repo/packages/libreadline8t64_8.3-4_amd64.deb
(Stored with Git LFS)
BIN
provisioning/offline-repo/packages/libreadline8t64_8.3-4_amd64.deb
(Stored with Git LFS)
Binary file not shown.
BIN
provisioning/offline-repo/packages/libsqlite3-0_3.46.1-9ubuntu0.2_amd64.deb
(Stored with Git LFS)
BIN
provisioning/offline-repo/packages/libsqlite3-0_3.46.1-9ubuntu0.2_amd64.deb
(Stored with Git LFS)
Binary file not shown.
BIN
provisioning/offline-repo/packages/libtk8.6_8.6.17-1build1_amd64.deb
(Stored with Git LFS)
BIN
provisioning/offline-repo/packages/libtk8.6_8.6.17-1build1_amd64.deb
(Stored with Git LFS)
Binary file not shown.
BIN
provisioning/offline-repo/packages/openssl_3.5.5-1ubuntu3.5_amd64.deb
(Stored with Git LFS)
BIN
provisioning/offline-repo/packages/openssl_3.5.5-1ubuntu3.5_amd64.deb
(Stored with Git LFS)
Binary file not shown.
BIN
provisioning/offline-repo/packages/python3-tk_3.14.3-0ubuntu2_amd64.deb
(Stored with Git LFS)
BIN
provisioning/offline-repo/packages/python3-tk_3.14.3-0ubuntu2_amd64.deb
(Stored with Git LFS)
Binary file not shown.
BIN
provisioning/offline-repo/packages/python3.14-tk_3.14.4-1ubuntu0.2_amd64.deb
(Stored with Git LFS)
BIN
provisioning/offline-repo/packages/python3.14-tk_3.14.4-1ubuntu0.2_amd64.deb
(Stored with Git LFS)
Binary file not shown.
BIN
provisioning/offline-repo/packages/readline-common_8.3-4_all.deb
(Stored with Git LFS)
BIN
provisioning/offline-repo/packages/readline-common_8.3-4_all.deb
(Stored with Git LFS)
Binary file not shown.
|
|
@ -5,23 +5,6 @@ LOG_FILE="${LOG_FILE:-/var/log/blueforce-install.log}"; STATE_DIR="${STATE_DIR:-
|
|||
[[ "${1:-}" == --check ]] && CHECK_MODE=1
|
||||
OFFLINE="${BF_OFFLINE:-0}"; SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
log() { echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) [18-final-check] $1" | tee -a "$LOG_FILE"; }
|
||||
|
||||
# Operator GUI runtime gate. The field application is the Python GUI (bfos), and
|
||||
# tkinter is a separate package on Ubuntu: a minimal image has python3 but no
|
||||
# window toolkit, so the operator would be left with no working entry point and
|
||||
# no network to fix it. Checked here because every install path reaches this
|
||||
# module, offline or not. When the GUI is unavailable the terminal console still
|
||||
# works, so this reports the degradation instead of aborting the install.
|
||||
if python3 -c 'import tkinter' >/dev/null 2>&1; then
|
||||
log 'OK: operatör arayüzü (tkinter) hazır'
|
||||
else
|
||||
log 'WARN: tkinter yok; operatör arayüzü açılamaz. Terminal konsolu çalışır: sudo bf --tui'
|
||||
log 'WARN: python3-tk paketi bu imajda eksik (offline depoda pinli: provisioning/offline-repo/manifests/base-packages.txt)'
|
||||
fi
|
||||
if [[ "$CHECK_MODE" == 1 ]]; then
|
||||
command -v bf >/dev/null 2>&1 || log 'WARN(check): bf komutu PATH üzerinde yok; kurulum bf simgesini oluşturur'
|
||||
fi
|
||||
|
||||
if [[ "$OFFLINE" == 1 ]]; then
|
||||
# Only local gates are meaningful offline. No central peer, handshake, or READY claim.
|
||||
for g in 01-precheck 02-system 03-user 04-hostname 05-network 06-wireguard 07-ssh 08-rdp 10-docker 11-meg 12-monitoring 13-firewall 14-update-policy 15-logrotate 16-gui 17-healthcheck; do
|
||||
|
|
|
|||
BIN
tests/__pycache__/test_bfos_gui_static.cpython-311.pyc
Normal file
BIN
tests/__pycache__/test_bfos_gui_static.cpython-311.pyc
Normal file
Binary file not shown.
|
|
@ -146,15 +146,7 @@ for column in package version architecture sha256 source; do
|
|||
done
|
||||
|
||||
# 7. No secrets, keys, or device identities in the offline repository assets.
|
||||
#
|
||||
# The committed built/ index is excluded: it is byte-for-byte apt-ftparchive
|
||||
# output over third-party packages, and upstream descriptions legitimately
|
||||
# contain the trigger words as prose (polkit's description ends "...without
|
||||
# being asked for their password:"), so scanning it reports the packages, not a
|
||||
# leak. Nothing is hidden by this: any secret that reached a manifest or a
|
||||
# README would still be caught below, and build-index.sh embeds no credentials
|
||||
# of its own -- its records are package name/version/sha256/size/source.
|
||||
if grep -RniE --exclude-dir=.git --exclude-dir=built \
|
||||
if grep -RniE --exclude-dir=.git \
|
||||
'(BEGIN [A-Z ]*PRIVATE KEY|(password|passwd|token|api[_-]?key|secret)[[:space:]]*[:=]|AKIA[0-9A-Z]{16}|BF-[0-9]{8})' \
|
||||
"$OFFLINE_REPO"; then
|
||||
fail 'secret-like or device-specific value found in provisioning/offline-repo'
|
||||
|
|
@ -425,12 +417,6 @@ cat > "$STUB_BIN/dpkg-deb" <<'STUB'
|
|||
#!/usr/bin/env bash
|
||||
# Test stub: real dpkg-deb reads the control member; the identity is read from
|
||||
# the <package>_<version>_<arch>.deb file name instead.
|
||||
#
|
||||
# The output shape mirrors the real tool exactly, which matters more than it
|
||||
# looks: dpkg-deb prints a BARE VALUE when one field is requested and
|
||||
# "<Field>: <value>" when several are, and callers exist in both styles. A stub
|
||||
# that always emitted one shape let a parser break the other pass every test --
|
||||
# the real pool came out empty while this suite stayed green.
|
||||
set -euo pipefail
|
||||
[[ "${1:-}" == '-f' ]] || exit 1
|
||||
file="${2:-}"
|
||||
|
|
@ -443,28 +429,14 @@ esac
|
|||
name="${base%.deb}"; arch="${name##*_}"; rest="${name%_*}"
|
||||
version="${rest##*_}"; package="${rest%_*}"
|
||||
[[ -n "$package" && -n "$version" && -n "$arch" ]] || exit 1
|
||||
|
||||
# dpkg-deb prints a BARE VALUE for one requested field and "<Field>: <value>"
|
||||
# for several. Both shapes must be reproduced: a stub that always emitted one
|
||||
# of them let a reader that only handled the other pass every run, and the real
|
||||
# pool came out empty while this suite stayed green.
|
||||
if [[ $# -eq 1 ]]; then
|
||||
case "$1" in
|
||||
for field in "$@"; do
|
||||
case "$field" in
|
||||
Package) printf '%s\n' "$package" ;;
|
||||
Version) printf '%s\n' "$version" ;;
|
||||
Architecture) printf '%s\n' "$arch" ;;
|
||||
*) printf '\n' ;;
|
||||
esac
|
||||
else
|
||||
for field in "$@"; do
|
||||
case "$field" in
|
||||
Package) printf 'Package: %s\n' "$package" ;;
|
||||
Version) printf 'Version: %s\n' "$version" ;;
|
||||
Architecture) printf 'Architecture: %s\n' "$arch" ;;
|
||||
*) printf '\n' ;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
STUB
|
||||
cat > "$STUB_BIN/apt-ftparchive" <<'STUB'
|
||||
#!/usr/bin/env bash
|
||||
|
|
@ -569,11 +541,6 @@ rc=0; out="$(bash "$BUILD_INDEX" --packages "$PKG_OUT" --output "$FOREIGN_OUT" -
|
|||
|
||||
# The real build.
|
||||
OUT="$TMP/owner-built"
|
||||
# Snapshot the committed bundle directory before this build. The assertion below
|
||||
# is about THIS build not writing there -- not about the directory being empty:
|
||||
# a maintainer's machine may hold an untracked/committed real build, and an
|
||||
# absolute "must be clean" check reported that legitimate bundle as test spill.
|
||||
built_state_before="$(git -C "$REPO_ROOT" status --porcelain -- "provisioning/offline-repo/built" 2>/dev/null || true)"
|
||||
rc=0; out="$(bash "$BUILD_INDEX" --packages "$PKG_OUT" --output "$OUT" --manifest-dir "$TMP/m" --manifest-out "$TMP/repo-manifest.yaml" 2>&1)" || rc=$?
|
||||
[[ "$rc" -eq 0 ]] && pass 'build-index.sh builds a bundle from the accepted pool' || { fail "build-index.sh build failed (exit $rc)"; printf '%s\n' "$out" >&2; }
|
||||
for artifact in Packages Packages.gz packages.lock.tsv SHA256SUMS; do
|
||||
|
|
@ -640,27 +607,9 @@ bundle_after="$(find "$OUT" -type f -exec sha256sum {} + | sort)"
|
|||
record_after="$(sha256sum "$TMP/repo-manifest.yaml" | awk '{print $1}')"
|
||||
[[ "$rc" -eq 0 && "$bundle_before" == "$bundle_after" ]] && pass 'rebuilding an unchanged pool leaves the bundle byte-identical' || fail 'rebuilding an unchanged pool changed the bundle'
|
||||
grep -q 'DEĞİŞİKLİK YOK' <<<"$out" && pass 'build-index.sh reports the unchanged bundle instead of rewriting it' || fail 'build-index.sh must report an unchanged bundle'
|
||||
# The guard must accept this script's own output as its own. In production the
|
||||
# record lives INSIDE the output directory (--manifest-out built/repo-manifest.yaml),
|
||||
# and the earlier fixtures wrote it outside, so a guard that rejected
|
||||
# repo-manifest.yaml as a foreign file passed every run while a real rebuild
|
||||
# stopped with "bu depoya ait olmayan dosya". Mirror the real layout.
|
||||
REBUILD_OUT="$TMP/rebuild-out"
|
||||
mkdir -p "$REBUILD_OUT"
|
||||
bash "$BUILD_INDEX" --packages "$PKG_OUT" --output "$REBUILD_OUT" --manifest-dir "$TMP/m" >/dev/null 2>&1
|
||||
[[ -f "$REBUILD_OUT/repo-manifest.yaml" ]] || fail 'the record was not written inside the output directory'
|
||||
rc_again=0; out_again="$(bash "$BUILD_INDEX" --packages "$PKG_OUT" --output "$REBUILD_OUT" --manifest-dir "$TMP/m" 2>&1)" || rc_again=$?
|
||||
if [[ "$rc_again" -eq 0 ]] && ! grep -q 'bu depoya ait olmayan dosya' <<<"$out_again"; then
|
||||
pass 'rebuilding the same output directory is accepted (its own record is not foreign)'
|
||||
else
|
||||
fail "a second build over its own output failed (exit $rc_again)"
|
||||
printf '%s\n' "$out_again" >&2
|
||||
fi
|
||||
[[ "$record_before" == "$record_after" ]] && pass 'an unchanged rebuild leaves the repository record untouched' || fail 'an unchanged rebuild must not restamp the repository record'
|
||||
git_status_note="$(git -C "$REPO_ROOT" status --porcelain -- "provisioning/offline-repo/built" 2>/dev/null || true)"
|
||||
[[ "$git_status_note" == "$built_state_before" ]] \
|
||||
&& pass 'the test build never touches the committed bundle directory' \
|
||||
|| fail "the test build changed provisioning/offline-repo/built: before=[$built_state_before] after=[$git_status_note]"
|
||||
[[ -z "$git_status_note" ]] && pass 'the test build never touches the committed bundle directory' || fail "the test build wrote into provisioning/offline-repo/built: $git_status_note"
|
||||
|
||||
# A missing pin: report, then stop, without touching the previous bundle.
|
||||
rm -f "$PKG_OUT/rustdesk_9.9.9-lab-fixture_amd64.deb"
|
||||
|
|
|
|||
|
|
@ -1011,41 +1011,12 @@ class TestCli(unittest.TestCase):
|
|||
self.assertIn("yalnızca Türkçe", err.getvalue())
|
||||
|
||||
def test_invalid_repository_is_a_usage_error(self):
|
||||
# This asserts the terminal console's own repository resolution. The
|
||||
# flag is explicit because --repo is valid for the GUI too: without
|
||||
# --tui the router would hand the call to the window and the assertion
|
||||
# would measure nothing (it also hangs a test runner with a display).
|
||||
err = io.StringIO()
|
||||
with mock.patch("sys.stderr", err):
|
||||
code = cli.main(["--tui", "--repo", os.path.join(self.tmp.name, "not-a-repo")])
|
||||
code = cli.main(["--repo", os.path.join(self.tmp.name, "not-a-repo")])
|
||||
self.assertEqual(config.EXIT_USAGE, code)
|
||||
self.assertIn("Blueforce deposu", err.getvalue())
|
||||
|
||||
def test_gui_is_the_default_surface(self):
|
||||
"""Bayraksız çağrı grafik arayüze gider (varsayılan davranış)."""
|
||||
args = build_args([])
|
||||
self.assertFalse(cli._wants_tui(args))
|
||||
|
||||
def test_tui_flag_forces_the_terminal_console(self):
|
||||
self.assertTrue(cli._wants_tui(build_args(["--tui"])))
|
||||
self.assertFalse(cli._wants_tui(build_args(["--gui"])))
|
||||
|
||||
def test_terminal_only_flags_stay_in_the_terminal(self):
|
||||
"""Rapor ve terminal ayarı bayrakları GUI'ye kaptırılmaz."""
|
||||
for argv in (["--list"], ["--list-targets"], ["--check"], ["--no-color"]):
|
||||
self.assertTrue(cli._wants_tui(build_args(argv)), argv)
|
||||
# Dil bayrağı yalnız varsayılandan FARKLI verildiğinde terminale çeker;
|
||||
# --lang tr varsayılanın kendisidir ve GUI'yi engellemez.
|
||||
self.assertTrue(cli._wants_tui(build_args(["--lang", "en"])))
|
||||
self.assertFalse(cli._wants_tui(build_args(["--lang", "tr"])))
|
||||
|
||||
def test_gui_and_tui_together_are_refused(self):
|
||||
err = io.StringIO()
|
||||
with mock.patch("sys.stderr", err):
|
||||
code = cli.main(["--gui", "--tui"])
|
||||
self.assertEqual(config.EXIT_USAGE, code)
|
||||
self.assertIn("birlikte kullanılamaz", err.getvalue())
|
||||
|
||||
def test_list_is_non_interactive_and_covers_21_operations(self):
|
||||
out = io.StringIO()
|
||||
with mock.patch("sys.stdout", out):
|
||||
|
|
|
|||
|
|
@ -169,9 +169,7 @@ class TestHeadlessAndTkinter(StaticCase):
|
|||
self.assertIsNotNone(message)
|
||||
self.assertIn("DISPLAY", message)
|
||||
self.assertIn("SSH", message)
|
||||
# Grafik arayüz açılamadığında önerilen yol aynı uygulamanın terminal
|
||||
# konsoludur; bash menü artık yedek (bkz. TERMINAL_MENU_HINT).
|
||||
self.assertIn("bf --tui", message)
|
||||
self.assertIn("bf-menu", message)
|
||||
self.assertIn("python3 -m bfos.ui_gui", message)
|
||||
|
||||
def test_display_and_wayland_are_accepted(self) -> None:
|
||||
|
|
@ -184,14 +182,14 @@ class TestHeadlessAndTkinter(StaticCase):
|
|||
message = ui.tkinter_missing_message("No module named '_tkinter'")
|
||||
self.assertIn("python3-tk", message)
|
||||
self.assertIn("apt", message)
|
||||
self.assertIn("bf --tui", message)
|
||||
self.assertIn("bf-menu", message)
|
||||
self.assertIn("_tkinter", message)
|
||||
|
||||
def test_window_start_error_is_turkish(self) -> None:
|
||||
message = ui.window_start_error(RuntimeError("no display name and no $DISPLAY"))
|
||||
self.assertIn("Pencere açılamadı", message)
|
||||
self.assertIn("ssh -X", message)
|
||||
self.assertIn("bf --tui", message)
|
||||
self.assertIn("bf-menu", message)
|
||||
|
||||
def test_import_does_not_create_a_window(self) -> None:
|
||||
# tkinter varsa bile modul import'u bir Tk koku olusturmamalidir:
|
||||
|
|
@ -224,80 +222,7 @@ class TestHeadlessAndTkinter(StaticCase):
|
|||
contextlib.redirect_stderr(stderr):
|
||||
code = ui.main([])
|
||||
self.assertEqual(code, 3)
|
||||
# Aynı uygulamanın terminal konsoluna yönlendirmeli (bf --tui).
|
||||
self.assertIn("bf --tui", stderr.getvalue())
|
||||
|
||||
|
||||
class TestRootGate(StaticCase):
|
||||
"""Tam yetkili GUI: yazma işlemleri root ister, raporlar her zaman açık.
|
||||
|
||||
Katalogun kendi `destructive` işareti ölçüt alınır (bkz. ui_gui
|
||||
_normalize_operation); bu yüzden testler katalogdan örnek seçer, sabit
|
||||
isimlere bağlanmaz.
|
||||
"""
|
||||
|
||||
def test_is_root_reflects_the_effective_uid(self) -> None:
|
||||
original = os.geteuid
|
||||
try:
|
||||
os.geteuid = lambda: 0
|
||||
self.assertTrue(ui.is_root())
|
||||
self.assertTrue(ui.write_operations_enabled())
|
||||
os.geteuid = lambda: 1000
|
||||
self.assertFalse(ui.is_root())
|
||||
self.assertFalse(ui.write_operations_enabled())
|
||||
finally:
|
||||
os.geteuid = original
|
||||
|
||||
def test_destructive_operations_require_root(self) -> None:
|
||||
writes = [op for op in self.backend.list_operations() if op.destructive]
|
||||
self.assertTrue(writes, "katalogda yazma işlemi yok; kapı test edilemez")
|
||||
for op in writes:
|
||||
self.assertTrue(op.needs_root,
|
||||
f"{op.id} yıkıcı ama needs_root değil")
|
||||
|
||||
def test_read_only_operations_do_not_require_root(self) -> None:
|
||||
reports = [op for op in self.backend.list_operations() if not op.destructive]
|
||||
self.assertTrue(reports, "katalogda salt-okunur işlem yok")
|
||||
frozen = [op.id for op in reports if op.needs_root]
|
||||
self.assertEqual([], frozen,
|
||||
"salt-okunur işlemler root istememeli: " + ", ".join(frozen))
|
||||
|
||||
def test_notice_names_the_command_to_get_privileges(self) -> None:
|
||||
self.assertIn("sudo bf", ui.ROOT_REQUIRED_NOTICE)
|
||||
self.assertIn("sudo bf", ui.NON_ROOT_DISABLED_HINT)
|
||||
|
||||
def test_run_plan_refuses_a_root_plan_without_root(self) -> None:
|
||||
"""Son savunma hattı: çalıştırma tek noktadan geçer."""
|
||||
plan = ui.CommandPlan(
|
||||
commands=(("true",),),
|
||||
destructive=True,
|
||||
requires_root=True,
|
||||
operation_id="install-local",
|
||||
)
|
||||
original = os.geteuid
|
||||
try:
|
||||
os.geteuid = lambda: 1000
|
||||
result = ui.run_plan(plan)
|
||||
finally:
|
||||
os.geteuid = original
|
||||
self.assertFalse(result.ok)
|
||||
self.assertEqual(2, result.exit_code)
|
||||
self.assertIn("yönetici yetkisi", result.output.lower())
|
||||
|
||||
def test_run_plan_allows_a_root_plan_when_root(self) -> None:
|
||||
plan = ui.CommandPlan(
|
||||
commands=(("true",),),
|
||||
destructive=True,
|
||||
requires_root=True,
|
||||
operation_id="install-local",
|
||||
)
|
||||
original = os.geteuid
|
||||
try:
|
||||
os.geteuid = lambda: 0
|
||||
result = ui.run_plan(plan)
|
||||
finally:
|
||||
os.geteuid = original
|
||||
self.assertTrue(result.ok, result.output)
|
||||
self.assertIn("bf-menu", stderr.getvalue())
|
||||
|
||||
|
||||
class TestSimpleModeLayout(StaticCase):
|
||||
|
|
|
|||
Loading…
Reference in a new issue