200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Bir yaklaşım IAC (Kod Olarak Altyapı) yalnızca depoda depolanan koddan değil, aynı zamanda bu kodu çevreleyen kişilerden ve süreçlerden de oluşur. Yazılım geliştirmeden altyapı yönetimine ve açıklamasına kadar olan yaklaşımları yeniden kullanmak mümkün müdür? Yazıyı okurken bu fikri aklınızda tutmanızda fayda var.

İngilizce sürümü

Bu benim transkripsiyonum Kütüphaneler üzerinde DevopsConf 2019-05-28.

Slaytlar ve videolar

Bash geçmişi olarak altyapı

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Diyelim ki yeni bir projeye geldiniz ve size şunu söylediler: “Bizim Kod Olarak Altyapı". Gerçekte ortaya çıkıyor Bash geçmişi olarak altyapı veya örneğin Bash geçmişi olarak belgeler. Bu çok gerçek bir durum, örneğin benzer bir durum Denis Lysenko tarafından bir konuşmasında anlatılmıştı. Tüm altyapıyı nasıl değiştirebilir ve sağlıklı bir şekilde uyumaya başlayabilirsiniz?proje için bash geçmişinden nasıl tutarlı bir altyapı elde ettiklerini anlattı.

Biraz arzuyla şunu söyleyebiliriz Bash geçmişi olarak altyapı bu kod gibidir:

  1. Yeniden üretilebilirlik: Bash geçmişini alabilir, komutları oradan çalıştırabilir ve bu arada, çıktı olarak çalışan bir konfigürasyon elde edebilirsiniz.
  2. versiyonlama: Kimin içeri girdiğini ve ne yaptığını biliyorsunuz, yine bunun sizi çıkışta çalışan bir konfigürasyona götüreceği de bir gerçek değil.
  3. tarih: Kimin ne yaptığının hikayesi. yalnızca sunucuyu kaybederseniz kullanamazsınız.

Ne yapmalı?

Kod Olarak Altyapı

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Böyle garip bir durum bile Bash geçmişi olarak altyapı kulaklarından tutarak çekebilirsin Kod Olarak Altyapıancak eski güzel LAMP sunucusundan daha karmaşık bir şey yapmak istediğimizde, bu kodun bir şekilde değiştirilmesi, değiştirilmesi, geliştirilmesi gerektiği sonucuna varacağız. Daha sonra aradaki paralellikleri ele almak istiyoruz. Kod Olarak Altyapı ve yazılım geliştirme.

KURU

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Bir depolama sistemi geliştirme projesinde bir alt görev vardı SDS'yi periyodik olarak yapılandırın: Yeni bir sürüm yayınlıyoruz - daha ileri testler için yayınlanması gerekiyor. Görev son derece basittir:

  • Buraya ssh aracılığıyla giriş yapın ve komutu yürütün.
  • dosyayı oraya kopyalayın.
  • Buradaki yapılandırmayı düzeltin.
  • hizmeti orada başlat
  • ...
  • KAR!

Açıklanan mantık için bash, özellikle projenin ilk aşamalarında, henüz yeni başladığında fazlasıyla yeterli. Bu bash kullanman kötü değil, ancak zamanla benzer ancak biraz farklı bir şeyin dağıtılması yönünde istekler var. Aklıma ilk gelen kopyala-yapıştır. Ve şimdi elimizde neredeyse aynı şeyi yapan çok benzer iki komut dosyası var. Zamanla komut dosyalarının sayısı arttı ve farklı komut dosyaları arasında senkronize edilmesi gereken bir kurulumu dağıtmak için belirli bir iş mantığı olduğu gerçeğiyle karşı karşıya kaldık, bu oldukça karmaşık.

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Meğer KURU (Kendini Tekrar Etme) diye bir uygulama varmış. Buradaki fikir mevcut kodu yeniden kullanmaktır. Kulağa basit geliyor ama buna hemen gelmedik. Bizim durumumuzda bu banal bir fikirdi: yapılandırmaları komut dosyalarından ayırmak. Onlar. kurulumun ayrı olarak nasıl dağıtıldığına ilişkin iş mantığı, ayrı ayrı yapılandırılır.

CFM için KATI

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Zamanla proje büyüdü ve doğal devam Ansible'ın ortaya çıkışıydı. Ortaya çıkmasının ana nedeni ekipte uzmanlık olması ve bash'ın karmaşık mantık için tasarlanmamasıdır. Ansible aynı zamanda karmaşık bir mantık da içermeye başladı. Karmaşık mantığın kaosa dönüşmesini önlemek için yazılım geliştirmede kodu düzenleme ilkeleri vardır. SAĞLAM Ayrıca, örneğin Grigory Petrov, "Bir BT uzmanının neden kişisel bir markaya ihtiyacı var" raporunda, bir kişinin bazı sosyal varlıklarla çalışmasını kolaylaştıracak şekilde tasarlandığı sorusunu gündeme getirdi; yazılım geliştirmede bunlar nesnelerdir. Bu iki fikri birleştirip geliştirmeye devam edersek, şunu da kullanabileceğimizi fark edeceğiz: SAĞLAM gelecekte bu mantığın bakımını ve değiştirilmesini kolaylaştırmak için.

Tek Sorumluluk İlkesi

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Her sınıf yalnızca bir görevi yerine getirir.

Kodları karıştırıp yekpare ilahi spagetti canavarları yaratmanıza gerek yok. Altyapı basit tuğlalardan oluşmalıdır. Ansible oyun kitabını küçük parçalara bölerseniz, Ansible rollerini okursanız, bunların bakımının daha kolay olduğu ortaya çıktı.

Açık Kapalı Prensibi

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Açık/kapalı prensibi.

  • Uzantıya açık: Bir varlığın davranışının yeni varlık türleri oluşturularak genişletilebileceği anlamına gelir.
  • Değişime kapalı: Bir varlığın davranışının genişletilmesinin bir sonucu olarak, o varlıkları kullanan kodda herhangi bir değişiklik yapılmamalıdır.

Başlangıçta test altyapısını sanal makinelere dağıttık ancak dağıtımın iş mantığının uygulamadan ayrı olması nedeniyle, baremetall'e sorunsuz bir şekilde yayılmayı ekledik.

Liskov Değiştirme Prensibi

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Barbara Liskov'un ikame ilkesi. Bir programdaki nesneler, programın doğru yürütülmesini değiştirmeden alt türlerinin örnekleriyle değiştirilebilir olmalıdır

Daha geniş anlamda bakarsanız orada uygulanabilecek herhangi bir projenin özelliği değil. SAĞLAM, genellikle CFM ile ilgilidir, örneğin başka bir projede kutulu bir Java uygulamasını çeşitli Java, uygulama sunucuları, veritabanları, işletim sistemi vb. üzerine dağıtmak gerekir. Bu örneği kullanarak daha ileri ilkeleri ele alacağım SAĞLAM

Bizim durumumuzda, altyapı ekibi içinde, eğer imbjava veya oraclejava rolünü kurduysak, çalıştırılabilir bir Java ikili dosyasına sahip olduğumuz konusunda bir anlaşma var. Bu gerekli çünkü Yukarı akış rolleri bu davranışa bağlıdır; Java'yı beklerler. Aynı zamanda bu, uygulama dağıtım mantığını değiştirmeden bir Java uygulamasını/versiyonunu diğeriyle değiştirmemize olanak tanır.

Buradaki sorun, bunun Ansible'da uygulanmasının imkansız olması ve bunun sonucunda ekip içinde bazı anlaşmaların ortaya çıkmasıdır.

Arayüz Ayrıştırma Prensibi

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Arayüz ayırma ilkesi: “Birçok müşteriye özel arayüz, tek bir genel amaçlı arayüzden daha iyidir.

Başlangıçta, uygulama dağıtımının tüm değişkenliğini tek bir Ansible playbook'a koymaya çalıştık, ancak bunu desteklemek zordu ve harici bir arayüz belirlediğimizde (müşteri 443 numaralı bağlantı noktasını bekler) yaklaşım, bireysel olarak bir altyapı oluşturulabilir. belirli bir uygulama için tuğlalar.

Bağımlılık Tersine Çevirme İlkesi

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Bağımlılığın tersine çevrilmesi ilkesi. Daha yüksek seviyelerdeki modüller, daha düşük seviyelerdeki modüllere bağlı olmamalıdır. Her iki modül türü de soyutlamalara bağlı olmalıdır. Soyutlamalar ayrıntılara bağlı olmamalıdır. Ayrıntılar soyutlamalara bağlı olmalıdır.

Burada örnek bir antimodele dayanacaktır.

  1. Müşterilerden birinin özel bulutu vardı.
  2. Bulut içinde sanal makineler sipariş ettik.
  3. Ancak bulutun doğası gereği uygulama dağıtımı, VM'nin hangi hipervizörde olduğuna bağlıydı.

Onlar. Yüksek düzey uygulama dağıtım mantığı, hipervizörün alt düzeylerine bağımlılıklarla akıyordu ve bu, bu mantığı yeniden kullanırken sorunlar anlamına geliyordu. Bunu yapma.

Etkileşim

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Kod olarak altyapı yalnızca kodla ilgili değildir, aynı zamanda kod ile insanlar arasındaki ilişkiyle, altyapı geliştiricileri arasındaki etkileşimlerle de ilgilidir.

otobüs faktörü

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Projenizde Vasya'nın olduğunu varsayalım. Vasya altyapınızla ilgili her şeyi biliyor, Vasya aniden ortadan kaybolursa ne olur? Bu çok gerçek bir durum çünkü ona bir otobüs çarpabilir. Bazen olur. Bu gerçekleşirse ve kodun yapısı, nasıl çalıştığı, görünümleri ve şifreleri hakkındaki bilgiler ekip arasında dağıtılmazsa, bir takım hoş olmayan durumlarla karşılaşabilirsiniz. Bu riskleri en aza indirmek ve bilgiyi ekip içinde dağıtmak için çeşitli yaklaşımlardan yararlanabilirsiniz.

Çift Devopsing

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Benzer değil şaka olarakyöneticilerin bira içtiğini, şifreleri değiştirdiğini ve çift programlamanın bir analogunu. Onlar. iki mühendis bir bilgisayarın, bir klavyenin başına oturur ve altyapınızı birlikte kurmaya başlar: bir sunucu kurmak, bir Ansible rolü yazmak vb. Kulağa hoş geliyor ama bizim için işe yaramadı. Ancak bu uygulamanın özel durumları işe yaradı. Yeni bir çalışan gelir, akıl hocası onunla birlikte gerçek bir görev üstlenir, çalışır ve bilgiyi aktarır.

Bir diğer özel durum ise olay çağrısıdır. Bir sorun sırasında, görevlilerden ve ilgili kişilerden oluşan bir grup toplanır, ekranını paylaşan ve düşünce akışını seslendiren bir lider atanır. Diğer katılımcılar liderin düşüncelerini takip eder, konsoldaki hileleri gözetler, kayıttaki bir satırı kaçırmadıklarını kontrol eder ve sistem hakkında yeni şeyler öğrenir. Bu yaklaşım çoğu zaman işe yaradı.

Kod incelemesi

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Öznel olarak, altyapı ve altyapının nasıl çalıştığı hakkındaki bilgiyi kod incelemesini kullanarak yaymak daha etkiliydi:

  • Altyapı, depodaki kodla tanımlanır.
  • Değişiklikler ayrı bir dalda gerçekleşir.
  • Birleştirme isteği sırasında altyapıdaki değişikliklerin deltasını görebilirsiniz.

Burada öne çıkan nokta, incelemecilerin bir programa göre teker teker seçilmesiydi; bir dereceye kadar olasılıkla yeni bir altyapı parçasına tırmanacaksınız.

Kod Stili

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Zamanla incelemeler sırasında kavgalar çıkmaya başladı çünkü... gözden geçirenlerin kendi stilleri vardı ve gözden geçirenlerin rotasyonu bunları farklı stillerle istifledi: 2 boşluk veya 4, camelCase veya Snake_case. Bunu hemen hayata geçirmek mümkün değildi.

  • İlk fikir linter kullanılmasını önermekti, sonuçta herkes mühendis, herkes akıllı. Ancak farklı editörler (işletim sistemi) uygun değildir
  • Bu, her sorunlu taahhüt için Slack'e yazan ve linter çıktısını ekleyen bir bot'a dönüştü. Ancak çoğu durumda yapılması gereken daha önemli şeyler vardı ve kod sabitlenmeden kalıyordu.

Yeşil Yapı Ustası

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Zaman geçiyor ve belirli testleri geçemeyen taahhütlerin ustaya kabul edilemeyeceği sonucuna vardık. İşte! Yazılım geliştirmede uzun süredir uygulanan Green Build Master'ı icat ettik:

  • Geliştirme ayrı bir şubede devam etmektedir.
  • Bu konu üzerinde testler yapılıyor.
  • Testler başarısız olursa kod ana bilgisayara aktarılamaz.

Bu kararı vermek çok acı vericiydi çünkü... Pek çok tartışmaya neden oldu ama buna değdi çünkü... İncelemelerde tarz farkı olmaksızın birleşme talepleri gelmeye başladı ve zamanla sorunlu alanların sayısı azalmaya başladı.

IaC Testi

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Stil kontrolüne ek olarak, örneğin altyapınızın gerçekten konuşlandırılıp dağıtılmadığını kontrol etmek için başka şeyler de kullanabilirsiniz. Veya altyapıdaki değişikliklerin para kaybına yol açmayacağını kontrol edin. Buna neden ihtiyaç duyulabilir? Soru karmaşık ve felsefi; Powershell'de bir şekilde sınır koşullarını kontrol etmeyen bir otomatik ölçekleyicinin bulunduğuna dair bir hikaye ile cevap vermek daha iyidir => gerekenden daha fazla VM oluşturuldu => müşteri planlanandan daha fazla para harcadı. Bu pek hoş bir durum değil ancak bu hatayı daha erken aşamalarda yakalamak oldukça mümkün olacaktır.

Birisi şu soruyu sorabilir: Neden karmaşık altyapıyı daha da karmaşık hale getiriyoruz? Altyapı testleri, tıpkı kod için olduğu gibi, basitleştirmeyle ilgili değil, altyapınızın nasıl çalışması gerektiğini bilmekle ilgilidir.

IaC Test Piramidi

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

IaC Testi: Statik Analiz

Altyapının tamamını bir kerede dağıtır ve çalışıp çalışmadığını kontrol ederseniz, bunun çok zaman aldığını ve çok fazla zaman gerektirdiğini görebilirsiniz. Bu nedenle temel hızlı çalışan bir şey olmalı, çok var ve birçok ilkel yeri kapsıyor.

Bash çetin bir iş

Önemsiz bir örneğe bakalım. geçerli dizindeki tüm dosyaları seçin ve başka bir konuma kopyalayın. Akla gelen ilk şey:

for i in * ; do 
    cp $i /some/path/$i.bak
done

Dosya adında boşluk varsa ne olur? Tamam, biz akıllıyız, tırnak işaretlerini nasıl kullanacağımızı biliyoruz:

for i in * ; do cp "$i" "/some/path/$i.bak" ; done

Tebrikler? HAYIR! Peki ya dizinde hiçbir şey yoksa, yani. küreselleşme işe yaramaz.

find . -type f -exec mv -v {} dst/{}.bak ;

Şimdi iyi misin? Hayır... Dosya adında ne olabileceğini unuttum n.

touch x
mv x  "$(printf "foonbar")"
find . -type f -print0 | xargs -0 mv -t /path/to/target-dir

Statik analiz araçları

Bir önceki adımdaki sorun tırnakları unuttuğumuz zaman yakalanabiliyor, bunun için doğada pek çok çare var Kabuk kontrolü, genel olarak birçoğu var ve büyük olasılıkla yığınınız için IDE'nizin altında bir linter bulabilirsiniz.

Dil
araç

darbe
Kabuk kontrolü

Yakut
RuboPolis

piton
Pilint

yanıtlayıcı '
Ansible Lint

IaC Testi: Birim Testleri

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Önceki örnekte gördüğümüz gibi linterler her şeye kadir değildir ve tüm sorunlu alanları işaret edemezler. Ayrıca yazılım geliştirmedeki testlere benzetilerek birim testlerini hatırlayabiliriz. İşte hemen aklıma geliyor kaçmak, Junit, rspec, Pytest. Peki ansible, şef, tuzluk ve onlar gibi diğerleriyle ne yapmalı?

En başında konuştuk SAĞLAM altyapımızın küçük tuğlalardan oluşması gerektiğini. Onların zamanı geldi.

  1. Altyapı, Ansible rolleri gibi küçük tuğlalara bölünmüştür.
  2. Docker veya VM gibi bir tür ortam dağıtılır.
  3. Ansible rolümüzü bu test ortamına uyguluyoruz.
  4. Her şeyin beklediğimiz gibi çalışıp çalışmadığını kontrol ediyoruz (testler yapıyoruz).
  5. Tamam olup olmadığına biz karar veririz.

IaC Testi: Birim Testi araçları

Soru: CFM testleri nelerdir? Komut dosyasını basitçe çalıştırabilir veya bunun için hazır çözümleri kullanabilirsiniz:

CFM
araç

yanıtlayıcı '
testinfra

Şef
Muayene

Şef
Sunucu özellikleri

tuz yığını
Goss

Testinfra örneği, kullanıcıların kontrol edilmesi test1, test2 var ve bir gruptalar sshusers:

def test_default_users(host):
    users = ['test1', 'test2' ]
    for login in users:
        assert host.user(login).exists
        assert 'sshusers' in host.user(login).groups

Ne seçeceksin? Soru karmaşık ve belirsiz, işte 2018-2019 için github'daki projelerdeki değişikliklere bir örnek:

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

IaC Test çerçeveleri

Şu soru ortaya çıkıyor: Hepsini nasıl bir araya getirip başlatacağız? Olabilmek al ve kendin yap Yeterli sayıda mühendis varsa. Veya çok fazla olmasa da hazır çözümler alabilirsiniz:

CFM
araç

yanıtlayıcı '
molekül

Şef
Test Mutfak

Terraform
Terratest

2018-2019 için github'daki projelerdeki değişikliklere örnek:

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Molekül vs. Test mutfağı

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Başlangıçta biz testkitchen'ı kullanmayı denedim:

  1. Paralel olarak bir VM oluşturun.
  2. Ansible rollerini uygulayın.
  3. Denetimi çalıştırın.

25-35 rol için 40-70 dakika çalıştı, bu uzun bir süreydi.

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Bir sonraki adım jenkins/docker/ansible/molecule'e geçişti. İdeolojik olarak her şey aynı

  1. Lint oyun kitapları.
  2. Rolleri sıralayın.
  3. Kapsayıcıyı başlat
  4. Ansible rollerini uygulayın.
  5. Testinfra'yı çalıştırın.
  6. İdempotens'i kontrol edin.

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

40 rol için astarlama ve bir düzine test yaklaşık 15 dakika sürmeye başladı.

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Hangisinin seçileceği, kullanılan yığın, ekipteki uzmanlık vb. gibi birçok faktöre bağlıdır. burada herkes Birim test sorusunun nasıl kapatılacağına kendisi karar verir

IaC Testi: Entegrasyon Testleri

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Altyapı test piramidinin bir sonraki adımı entegrasyon testleri olacaktır. Birim testlerine benzerler:

  1. Altyapı, Ansible rolleri gibi küçük tuğlalara bölünmüştür.
  2. Docker veya VM gibi bir tür ortam dağıtılır.
  3. Bu test ortamı için geçerlidir set Yanıtlayıcı roller.
  4. Her şeyin beklediğimiz gibi çalışıp çalışmadığını kontrol ediyoruz (testler yapıyoruz).
  5. Tamam olup olmadığına biz karar veririz.

Kabaca söylemek gerekirse, birim testlerinde olduğu gibi sistemin tek bir öğesinin performansını kontrol etmiyoruz, sunucunun bir bütün olarak nasıl yapılandırıldığını kontrol ediyoruz.

IaC Testi: Uçtan Uca Testler

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Piramidin tepesinde Uçtan Uca testler bizi karşılıyor. Onlar. Ayrı bir sunucunun, ayrı bir betiğin veya altyapımızın ayrı bir tuğlasının performansını kontrol etmiyoruz. Birçok sunucunun birbirine bağlı olup olmadığını kontrol ediyoruz, altyapımız beklediğimiz gibi çalışıyor. Ne yazık ki, hiç hazır kutulu çözümler görmedim, muhtemelen çünkü... Altyapı genellikle benzersizdir ve şablon oluşturmak ve test için bir çerçeve oluşturmak zordur. Sonuçta herkes kendi çözümünü üretiyor. Talep var ama cevap yok. Bu nedenle, başkalarını sağlam düşüncelere itmek veya her şeyin bizden çok önce icat edildiği gerçeğine burnumu sokmak için size ne olduğunu anlatacağım.

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Zengin geçmişi olan bir proje. Büyük organizasyonlarda kullanılmaktadır ve muhtemelen her birinizin yolu dolaylı olarak onunla kesişmiştir. Uygulama birçok veritabanını, entegrasyonu vb. destekler. Altyapının nasıl görünebileceğini bilmek, çok sayıda liman işçisi tarafından oluşturulan dosyalardan oluşur ve hangi testlerin hangi ortamda çalıştırılacağını bilmek Jenkins'in işidir.

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Bu şema, çerçeveye kadar oldukça uzun bir süre çalıştı. araştırma bunu Openshift'e aktarmaya çalışmadık. Kaplar aynı kalıyor ancak başlatma ortamı değişti (tekrar merhaba DRY).

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Araştırma fikri daha da ileri gitti ve açık vardiyada, altyapının bir konteynere nasıl dağıtılacağına dair bilgiyi paketlemenize olanak tanıyan APB (Ansible Playbook Bundle) gibi bir şey buldular. Onlar. Altyapının nasıl konuşlandırılacağına dair tekrarlanabilir, test edilebilir bir bilgi noktası vardır.

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Heterojen bir altyapıyla karşılaşıncaya kadar tüm bunlar kulağa hoş geliyordu: Testler için Windows'a ihtiyacımız vardı. Sonuç olarak neyin, nerede, nasıl dağıtılacağı ve test edileceği bilgisi jenkins'tedir.

Sonuç

200 Satır Altyapı Kodunun Test Edilmesinden Öğrendiklerim

Kod Olarak Altyapı

  • Depodaki kod.
  • İnsan etkileşimi.
  • Altyapı testi.

bağlantılar

Kaynak: habr.com

Yorum ekle