İçeriğe geç
academia.sh

Ders 12 / 14

Paketleme

Aynı kaynaktan üç dizin durumu ve üç dahil etme kuralıyla yapılan dokuz üretim 5 ayrı içerik verir; açık liste bu sayıyı 1'e indirir, arşiv özetini yalnız sıralı girdi ile kaynaktan türetilmiş damganın birlikte kullanılması tekleştirir ve derleme adımının ne zaman çalıştığı kurulumu 3 ayrı sonuçtan 1'e düşürür.

İçindekiler

Önceki ders aynı takımı üç eksenli bir matriste koşturdu ve kalan farkın gerçek ortam farkı olduğunu gösterdi. O ölçümün sessiz bir varsayımı vardı: her ortamda koşan şey aynı kaynaktı. Testler doğrudan çalışma dizininden okundu.

Bir proje başkasının kullanımına verildiğinde bu varsayım kendiliğinden sağlanmaz. Kaynak dizini olduğu gibi gitmez; bir dağıtım biçimine (distribution format) paketlenir, o paket taşınır ve karşı tarafta açılır. Bu dersin sorusu paketlemenin nasıl yapıldığı değil: aynı kaynaktan üretilen dağıtım kaç ayrı içerik verir, ve neyi sabitlemek bu sayıyı bire indirir?

Dağıtım Biçimi ve Derleme Sistemi

İki dağıtım biçimi ayrılır ve aradaki fark bu dersin son ölçümünün konusudur.

Kaynak dağıtımı kaynak dosyaları ve proje bildirimini taşır. Kurulan tarafta bir derleme adımı çalışır ve kurulacak ağacı üretir. Kurulmuş dağıtım ise bu adımın sonucunu taşır; kurulan tarafta yalnız açma işi kalır.

Bu iki biçimi üreten araç sınıfı derleme sistemidir (build system). Görevi üç sorunun yanıtını üretmektir: hangi dosyalar dağıtıma girecek, dağıtım hangi düzende yazılacak, ve derleme adımı ne zaman çalışacak. Bu kurs araç adı yazmaz; derleme sistemi burada üç işlevle modellenir — bir dahil etme kuralı, bir arşiv yazıcısı ve bir derleme adımı. Model gerçek bir arşiv üretmez, hiçbir dosya diske yazmaz ve hiçbir paket indirmez; ürettiği tek şey içerik özetleridir.

Üç Dizin Durumu

Dahil etme kuralının ne yapacağı, kaynağın yanında ne durduğuna bağlıdır. Bir çalışma dizini kaynaktan ibaret değildir: derleme artıkları, önbellek dosyaları ve yerel ayar dosyaları da orada birikir. Ölçüm üç durum tanımlar. Temiz dizin yalnız kaynağı taşır. Önbellekli dizinde bir üretilmiş dosya vardır. Artıklı dizinde ayrıca bir kayıt dosyası ve bir yerel ayar dosyası bulunur.

Üç dahil etme kuralı denenir. Her şeyi topla dizindeki her dosyayı alır. Desenle ele belirli uzantıları dışarıda bırakır. Açık liste yalnız bildirimde adı geçen dosyaları alır.

Ölçümün varsayımları:

  • KY15 — Kaynak ağacı sabittir ve üç durumda da aynıdır; durumlar yalnız kaynağın yanında duran dosyalarla ayrılır.
  • KY16 — Dağıtımın içeriği, dosya adları ve gövdelerinin ada göre sıralanmış özetidir; dizin listeleme sırası bu özete girmez.
  • KY17 — Arşiv özeti ise sıraya ve damgaya duyarlıdır; iki koşumun listeleme sırası ve koşum damgası kurgu değerlerle modellenir, gerçek bir saat okunmaz.
  • KY18 — Derleme adımı kaynaktan tek bir dosya üretir ve içine çalıştığı ortamın adını yazar. Gerçek bir derleme adımı bundan çok daha fazlasını yapar; modelin tuttuğu tek özellik, çıktısının çalıştığı ortama bağlı olmasıdır.
  • KY19 — Özetler kısaltılmış sekiz onaltılık basamaktır; iki özetin eşitliği içeriğin eşitliği olarak okunur.
  • KY20 — Hiçbir dosya diske yazılmaz, hiçbir arşiv üretilmez, hiçbir paket indirilmez; bütün üretim bellekte modellenir.
  • KY21 — Süre ölçülmez. Sayılan şey ayrı içerik, ayrı özet ve ayrı kurulum sayısıdır.

Ölçüm

"""Paketleme: ayni kaynaktan uretilen dagitim kac ayri icerik veriyor."""

import hashlib

KAYNAK = {
    "olcum/__init__.py": "from .indirim import indirim\n",
    "olcum/indirim.py": "def indirim(tutar, uye, kupon):\n    return tutar\n",
    "olcum/oran.json": '{"tavan": 20}\n',
    "testler/test_indirim.py": "def test_tavan():\n    pass\n",
    "BENIOKU.md": "# olcum\n",
    "proje.toml": '[proje]\nad = "olcum"\n',
}
ARTIK = {
    "temiz": {},
    "önbellekli": {"olcum/__onbellek__/indirim.onb": "derlenmis\n"},
    "artıklı": {"olcum/__onbellek__/indirim.onb": "derlenmis\n",
                "olcum/gecici.log": "kosum kaydi\n",
                "yerel_ayar.txt": "yol = /ev/kullanici\n"},
}
LISTE = ("olcum/__init__.py", "olcum/indirim.py", "olcum/oran.json",
         "proje.toml")
KURALLAR = {
    "her şeyi topla": lambda ad: True,
    "desenle ele": lambda ad: not ad.endswith((".onb", ".log")),
    "açık liste": lambda ad: ad in LISTE,
}


def dizin(durum):
    return {**KAYNAK, **ARTIK[durum]}


def ozet(metin):
    return hashlib.sha256(metin.encode()).hexdigest()[:8]


def icerik_ozeti(dosyalar):
    """Dagitimin icerigi: ad ve govde, adina gore sirali."""
    return ozet("".join(f"{a}\n{dosyalar[a]}" for a in sorted(dosyalar)))


def sec(durum, kural):
    d = dizin(durum)
    return {a: g for a, g in d.items() if KURALLAR[kural](a)}


print(f"{'dahil etme':<15s} " + " ".join(f"{d:>14s}" for d in ARTIK)
      + "  ayrı içerik")
tum = []
for kural in KURALLAR:
    satir, ozetler = [], []
    for durum in ARTIK:
        secim = sec(durum, kural)
        o = icerik_ozeti(secim)
        ozetler.append(o)
        tum.append(o)
        satir.append(f"{len(secim)}·{o}")
    print(f"{kural:<15s} " + " ".join(f"{s:>14s}" for s in satir)
          + f"{len(set(ozetler)):11d}")
print(f"dokuz üretim, {len(set(tum))} ayrı içerik")

print()
print(f"{'sıra kuralı':<18s} {'damga kuralı':<20s} {'koşum A':>9s} "
      f"{'koşum B':>9s}  ayrı")


def listele(dosyalar, kosum):
    return sorted(dosyalar, reverse=(kosum == "koşum B"))


def arsiv(dosyalar, sirali, kaynaktan_damga, kosum, damga):
    adlar = sorted(dosyalar) if sirali else listele(dosyalar, kosum)
    d = icerik_ozeti(dosyalar) if kaynaktan_damga else damga
    return ozet("".join(f"{a}\n{dosyalar[a]}" for a in adlar) + f"damga={d}\n")


SECIM = sec("artıklı", "açık liste")
DAMGA = {"koşum A": "d-101", "koşum B": "d-207"}
for s_ad, sirali in (("listeleme sırası", False), ("adına göre sıralı", True)):
    for d_ad, kaynaktan in (("koşum damgası", False),
                            ("kaynaktan türetilmiş", True)):
        a = [arsiv(SECIM, sirali, kaynaktan, k, DAMGA[k]) for k in DAMGA]
        print(f"{s_ad:<18s} {d_ad:<20s} {a[0]:>9s} {a[1]:>9s}"
              f"{len(set(a)):6d}")

print()


def derle(dosyalar, ortam):
    """Derleme adimi: kaynaktan bir dosya uretir."""
    return {**dosyalar, "olcum/_yapi.py": f'YAPILDI = "{ortam}"\n'}


kaynak_dagitimi = SECIM
kurulmus_dagitim = derle(SECIM, "üretim ortamı")
print(f"{'dağıtım biçimi':<20s} " + " ".join(f"{d:>10s}" for d in ARTIK)
      + "  ayrı kurulum")
for ad, kurulum in (("kaynak dağıtımı",
                     lambda o: icerik_ozeti(derle(kaynak_dagitimi, o))),
                    ("kurulmuş dağıtım",
                     lambda o: icerik_ozeti(kurulmus_dagitim))):
    o = [kurulum(d) for d in ARTIK]
    print(f"{ad:<20s} " + " ".join(f"{x:>10s}" for x in o)
          + f"{len(set(o)):13d}")
dahil etme               temiz     önbellekli        artıklı  ayrı içerik
her şeyi topla      6·3f5fd540     7·c6e0e7fa     9·5bd4ca54          3
desenle ele         6·3f5fd540     6·3f5fd540     7·f43474cf          2
açık liste          4·3f6d7475     4·3f6d7475     4·3f6d7475          1
dokuz üretim, 5 ayrı içerik

sıra kuralı        damga kuralı           koşum A   koşum B  ayrı
listeleme sırası   koşum damgası         0ef2d766  ed542e63     2
listeleme sırası   kaynaktan türetilmiş  f2347fb6  153d3f8d     2
adına göre sıralı  koşum damgası         0ef2d766  94813185     2
adına göre sıralı  kaynaktan türetilmiş  f2347fb6  f2347fb6     1

dağıtım biçimi            temiz önbellekli    artıklı  ayrı kurulum
kaynak dağıtımı        ca94ea4c   c836cc41   8cd3c4ae            3
kurulmuş dağıtım       47abe500   47abe500   47abe500            1

Dokuz Üretim, Beş İçerik

Üst tablo dersin ilk sayısını veriyor: aynı kaynaktan yapılan 9 üretim 5 ayrı içerik üretiyor.

Satırlar tek tek okunduğunda sayının nereden geldiği görülür. Her şeyi topla kuralı üç dizin durumunda 6, 7 ve 9 dosya alıyor ve 3 ayrı içerik veriyor. Bu kuralın sonucu kaynağa değil, kaynağın yanında ne durduğuna bağlıdır; aynı depodan çekilmiş iki çalışma dizini ayrı paket üretir.

Desenle ele kuralı iki durumda aynı sonucu veriyor — temiz ile önbellekli aynı özeti, 3f5fd540, taşıyor — çünkü elediği uzantı önbellek dosyasını yakalıyor. Üçüncü durumda ise yerel_ayar.txt dosyası desene takılmıyor ve içeriğe giriyor: 7 dosya, ayrı özet. Kural, saydığı şeyi bildiği kadar eleyebilir.

Açık liste üç durumda da 4 dosya ve tek bir özet, 3f6d7475, veriyor: 1 ayrı içerik. Aradaki fark yöntemseldir. İlk iki kural “neyin dışarıda kalacağını” söyler ve listelenmemiş her yeni dosya sessizce içeri girer. Üçüncü kural “neyin içeri gireceğini” söyler; listelenmemiş her dosya sessizce dışarıda kalır. Sessizliğin yönü değişir, ve tekleşme bu yön değişiminden gelir.

İki özet dokuz üretimin ikisinde birden geçiyor: 3f5fd540 hem her şeyi topla/temiz hem desenle ele/temiz hücrelerinde. Dokuz hücre, beş ayrı içerik; kuralların çakıştığı yerde sayı düşüyor.

Dosya sayıları bir ayrımı daha görünür kılıyor. Açık liste 4 dosya alıyor, oysa temiz dizinde 6 kaynak dosyası var. Dışarıda kalan ikisi testler/test_indirim.py ve BENIOKU.md. Bu bir kusur değil, bir karardır: dağıtım kurulan ağacı taşır, depodaki her şeyi değil. Test dosyası depoda kalır ve orada koşar; dağıtıma girdiğinde kurulan tarafın disk alanını ve içe aktarma ad uzayını kaplar. Aynı karar belge dosyası için de verilebilir ve tersi de savunulabilir — savunulamaz olan, kararın verilmemiş olmasıdır. İlk iki kuralda bu karar hiç verilmiyor; dosyanın dağıtıma girip girmeyeceğini adının uzantısı belirliyor.

Bildirimin İki İşi

Üç dahil etme kuralı da bir yerde yazılıdır ve o yer proje bildirimidir. Bildirim iki ayrı iş yapar ve ikisi sık sık aynı dosyada durduğu için karıştırılır.

Birinci iş: paketin kimliği. Ad, sürüm, bağımlılık bildirimi ve dağıtıma girecek dosyalar. Bunlar veriyi tanımlar; hangi araçla okundukları sonucu değiştirmez.

İkinci iş: derleme sisteminin seçimi. Dağıtımı hangi derleme sisteminin üreteceği ve o sistemin hangi arayüzle çağrılacağı. Bu bir yönergedir; sonucu doğrudan belirler.

Ayrımın pratik karşılığı şudur: birinci iş bildirimseldir ve iki ayrı araç aynı bildirimi okuyup aynı dosya kümesini seçer. İkinci iş bir seçimdir ve seçilen sisteme göre üretilen arşivin düzeni, damgası ve derleme adımının davranışı değişir. Ölçümün üst tablosu birinci işi, orta tablosu ikinci işi sınıyor.

Bu yüzden bir bildirimin “eksiksiz” olması iki ayrı anlama gelir. Dosya listesi eksiksizse dağıtımın içeriği tekleşir. Derleme sistemi ve çağrı arayüzü de yazılıysa, dağıtımı üreten her koşum aynı sistemi aynı biçimde çağırır. İkincisi yazılmadığında üretim aracın öntanımlısına düşer ve ortak tanımın çözümleme ölçümündeki durum tekrarlanır: karar verilmemiştir, o yüzden ortam verir.

Arşivi Sabitleyen İki Karar

İçeriğin tekleşmesi arşivin tekleşmesi anlamına gelmez. Orta tablo aynı dosya kümesini — açık liste kuralının seçtiği dört dosyayı — iki koşumda arşivliyor ve dört kural bileşimini yan yana koyuyor.

Üç bileşimde iki koşum 2 ayrı özet veriyor. Bir bileşimde 1.

Listeleme sırası kullanıldığında koşum A ve koşum B dosyaları ayrı düzende yazıyor; gövde aynı, bayt dizisi ayrı. Damga kaynaktan türetilse bile bu fark kalıyor: ikinci satır f2347fb6 ile 153d3f8d veriyor. Koşum damgası kullanıldığında ise sıra sabitlense bile fark kalıyor; üçüncü satır 0ef2d766 ile 94813185 veriyor.

Yalnız dördüncü satır 1 veriyor: sıra adına göre sabitlenmiş ve damga kaynaktan türetilmiş. İkisi birden gerekiyor, biri yetmiyor. Bu, yeniden üretilebilirliğin tanımıdır: aynı girdiden aynı çıktı, koşumdan koşuma.

Arşiv özetinin neden ayrıca ölçüldüğü de buradan anlaşılır. Kurulan taraf içeriği kendi hesaplayamaz; eline geçen şey bir arşivdir ve onu ancak baytları üzerinden doğrulayabilir. İçerik tek olsa bile arşiv baytları koşumdan koşuma değişiyorsa, iki arşivin aynı kaynaktan geldiği doğrulanamaz. Yeniden üretilebilirlik iddiası bu yüzden içerik düzeyinde değil, bayt düzeyinde kurulur.

Üçüncü satırdaki 0ef2d766 ile birinci satırdaki 0ef2d766 aynı olduğu için bir ayrıntı görülebiliyor: koşum A’nın listeleme sırası zaten adına göre sıralıdır, bu yüzden o koşumda iki sıra kuralı aynı sonucu verir. Fark yalnız koşum B’de ortaya çıkar. Bir yapılandırma kusuru her koşumda görünmez; görünmediği koşumda yok olduğu sanılır.

Derlemenin Ne Zaman Çalıştığı

Alt tablo son ölçümü veriyor ve iki dağıtım biçimini ayırıyor.

Kaynak dağıtımı üç dizin durumunda 3 ayrı kurulum veriyor. Nedeni tabloda görünmüyor ama modelde açıktır: derleme adımı kurulan tarafta çalışıyor ve ürettiği dosyaya kurulduğu ortamın adını yazıyor. Kurulan ağaç bu yüzden ortamdan ortama değişiyor. Dağıtımın kendisi tekti — dört dosya, tek özet — ama kurulum sonucu tek değil.

Kurulmuş dağıtım üç durumda da 1 ayrı kurulum veriyor: 47abe500. Derleme adımı bir kez, üretim tarafında çalıştı; kurulan taraf yalnız açıyor.

İkisi arasındaki fark derleme adımının nerede çalıştığıdır, ve bu bir dağıtım biçimi kararıdır. Kaynak dağıtımı derlemeyi kurulan tarafa taşır; karşılığında kurulan taraf kendi ortamına uygun bir çıktı üretebilir. Kurulmuş dağıtım derlemeyi bir kez yapar; karşılığında ortam farkını dağıtıma yansıtamaz.

Bu, kurulmuş dağıtımın bedelsiz olduğu anlamına gelmez. Derleme adımı ortamdan bir şey okuyorsa, kurulmuş dağıtım okuduğu değeri içine gömer ve artık yalnız o ortama uyar. O zaman dağıtımın hangi ortama uyduğunun paketin kendisinde yazılı olması gerekir; yazılı değilse kurulan taraf uymayan bir paketi açar ve hata kurulumdan çok sonra, çalışma sırasında görünür. Kaynak dağıtımının ürettiği 3 ayrı kurulum bir kusur değil, bu uyarlamanın kendisidir; kusur, üç ayrı sonucun beklenmiyor olmasıdır.

Bir kez üretilip her yere dağıtılan yapı çıktısı ilkesi DevOps Kültürü ve Temelleri kursunda işletim tarafında kurulmuştu. Buradaki ölçüm o ilkenin dil tarafındaki karşılığını sayıyla veriyor: ilke uygulandığında kurulum sonucu 1, uygulanmadığında ortam sayısı kadar.

Üç ölçümü tek cümlede birleştirmek gerekirse: aynı kaynaktan çıkan dağıtımın tek içerik vermesi için üç şeyin birden sabitlenmesi gerekir — dahil edilecek dosyaların açık listesi, arşivin yazım sırası ve damgası, ve derleme adımının hangi tarafta çalışacağı. Üçünden biri açık bırakıldığında sayı birden büyüktür ve büyüklüğü, açık bırakılan yerin ortamdan ne kadar etkilendiğine bağlıdır.

Özet

  • Dağıtım biçimi ikiye ayrılır: kaynak dağıtımı derleme adımını kurulan tarafa taşır, kurulmuş dağıtım o adımın sonucunu taşır.
  • Aynı kaynaktan yapılan 9 üretim 5 ayrı içerik verir; her şeyi topla kuralı 3, desenle ele 2, açık liste 1 ayrı içerik üretir.
  • Eleyen kurallar listelenmemiş dosyayı sessizce içeri alır; açık liste sessizce dışarıda bırakır. Tekleşme bu yön değişiminden gelir.
  • Arşiv özetinin tekleşmesi için sıranın ve damganın birlikte sabitlenmesi gerekir; dört bileşimden yalnız biri 1 ayrı özet verir, üçü 2.
  • Kaynak dağıtımı üç ortamda 3 ayrı kurulum, kurulmuş dağıtım 1 verir; dağıtımın kendisi tek olsa bile kurulum sonucu tek olmayabilir.

Sonraki Adım

Bu ders dağıtımı üretti ve içeriğini bir özetle adlandırdı. Özet, üretim tarafında hesaplanan bir sayıdır ve orada kalır. Paket bir paket kaydına gönderildiğinde ise ona bir ad ve bir sürüm verilir; kurulan taraf artık içeriği değil, adı ister. Sonraki dersin sorusu buradan doğar: yayımlanmış bir sürümün içeriği sonradan değişebilir mi, aynı ad iki ayrı içeriği taşıyabilir mi, ve taşıyabiliyorsa kilit dosyasının yazdığı sürüm numarası neyi garanti eder?

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat