Bicep makale serisinin dördüncü bölümünde for loop kullanımından bahsetmiştim. Bu bölümde ise yine for loop için kullandığım cümleyi, “birden fazla resource oluşturma gereksinimlerinde kod tekrarının önüne nasıl geçebileceğimizi” modüller ile anlatacağım.
Modül kavramını, “aynı türden kaynaklar için tekrar kullanılabilir bicep dosyaları oluşturmak” olarak kısaca tanımlayabiliriz. Bunu nesne yönelimli programlamadaki nesneler olarak da düşünebilirsiniz.
Modüllerin en büyük faydası da aslında burada ortaya çıkıyor. Bir kere yazdığınız bir modülü, farklı deployment’lar için tekrar tekrar kullanabildiğiniz gibi, modül içerisinde isimlendirme standartlarını belirleyebilir, parametrelere kısıt getirebilir ve modül detayını gizleyebilirsiniz (bunu bir sonraki bölümde anlatacağım).
Örnek olarak 5 tane modül hazırlayıp, bu modülleri daha önceki örneklerdeki gibi main.bicep içerisinde kullanacağım. Deployment sonunda bir App Service ve buna bağlı bir Application Insights ile, daha önceden tanımlı olan bir key vault üzerindeki değerleri App Service konfigürasyonu üzerine tanımlı halde gelmesini istiyorum. Bunun için 5 tane modül hazırlayacağım:
- Application Insights
- App Service
- App Service Config
- App Service Plan
- KeyVault Access Policies
NOT: Bütün kodlara GitHub üzerinden erişebilirsiniz.
İlk olarak Application Insights ile başlayalım. İlk olarak deployment’ı nereye yapacağımı belirten parametre tanımını yapıyorum. Burada varsayılan değer olarak da deployment’ın yapılacağım resource group’un location değerini atıyorum. İkinci parametre olarak da environmentCode ekliyorum. Buna da en az 3, en fazla 6 karakter olacak şekilde sınırlıyorum. Buradaki amacım ise deployment’ları dev/test gibi ayırıp, bir de numara vermek; d01, d02, t01 gibi düşünebilirsiniz. Son parametre de deploy edeceğimiz kaynağa bir kısa isim vermek (resourceAbbreviation), buna da en az 3, en fazla 6 karakter limiti ekliyorum.
Resim-1
Parametre tanımı bittikten sonra şimdi de kaynak tanımına geldi. Daha önceki bölümlerden de hatırlayacağınız gibi, yeni bir kaynak tanımı yapıyorum. Burada name parametresine atama yaparken, Resim-1‘de göreceğiniz gibi bir isimlendirme standartı uyguluyorum. Böylece environmentCode ve resourceAbbreviation parametrelerini kullanarak bu modülü kullanan herkesin belirlediğim standarta uymasını sağlayabilirim.
Son olarak da Application Insights kaynağı oluştuktan sonra, diğer modüllerde bana lazım olacak instrumentationKey ve connectionString değerlerini çıkış parametresi olarak tanımlıyorum. Böylece diğer modüllerde bu değerleri kullanabileceğim.
İkinci sırada App Service var. Öncelikle burada da ilk modülde olduğu gibi location, environmentCode ve resourceAbbreviation parametrelerini tanımlıyorum. Ek olarak serverFarmId adında bir parametre daha ekliyorum, bunu da App Service Plan ile eşleştirmek için kullanacağım.
Resim-2
App Service için kaynak tanımını da Resim-2‘deki gibi yaptıktan sonra, diğer modüller için gerekli olarak name, principalId ve tenantId bilgilerini alıyorum. Birazdan bahsedeceğim KeyVault’a erişim için gerekli yetkileri vermek için Identity ile ilgili tanımlara ihtiyacım olacak.
Üçüncü olarak App Service konfigürasyonu için de farklı bir modül tanımı yapacağım. Modülleri sadece kaynaklar için değil, kaynaklar içerisindeki diğer kısımlar için de yapabiliyoruz. Konfigürasyon için biraz fazla parametre tanımı gerekiyor. İlk olarak Resim-3‘de göreceğiniz parametreleri tanımlıyorum. Burada secure() decorator’ını kullandığım parametreleri, key vault’tan alacağım.
Resim-3
Kaynak tanımında ise, konfigürasyonunu yapacağımız ve haliyle de önceden tanımlı olması gereken App Service kaynağını existing keyword’ü ile tanımlıyorum. Sonra da App Settings ve Connection Strings için 2 farklı kaynak tanımı yapıyorum. Burada Application Insights için yaptığım tanımlarda, özellikle
ApplicationInsightsAgent_EXTENSION_VERSION, APPINSIGHTS_PROFILERFEATURE_VERSION ve APPINSIGHTS_SNAPSHOTFEATURE_VERSION değerleri, deployment sonrasında App Service’e gittiğinizde, Application Insights’ın Enabled olması için gerekli. Burada InstrumentationKey ve ConnectionString tanımı yapmak enable olması için yeterli olmuyor.
App Service’e bir API deploy edeceğimizi varsayarak da, JWT ile ilgili 3 tane daha tanım ekliyorum. Burada da bool tipindeki ValidateIssuer ve ValidateAudience değerlerini string’e convert etmem gerekiyor.
Resim-4
Son olarak da connection string için DbConnectionString, UserId ve Password tanımlarını yapıyorum. Burada DbConnectionString tipini, Azure SQL’e bağlanacağımı varsayarak SQLAzure seçiyorum. UserId ve Password tipi ise belirli bir tip olmadığından Custom olarak belirledim. Burada seçebileceğiniz tip çeşitleri:
- ApiHub
- Custom
- DocDb
- EventHub
- MySql
- NotificationHub
- PostgreSQL
- RedisCache
- ServiceBus
- SQLAzure
- SQLServer
Belki de ilk yapmam gereken modüle sıra geldi, App Service Plan. Standart parametrelere ek olarak, AppServicePlanSkuName adında bir parametre ekliyorum. Output olarak da AppServicePlanId, yani ServerFarmId bilgisini dönüyorum (Resim-5).
Resim-5
Örnek senaryodaki son modülde de key vault access policy tanımlarının yapacağım (Resim-6). Parametre olarak mevcutta kullanacağım key vault’un adı ile tanımlayacağım access policy’leri (birden fazla olacağı için object array tipinde) ekliyorum. Existing kullanarak mevcuttaki key vault’u tanımladıktan sonra, for loop kullanarak accessPolicies array’i içerisindeki access policy değerlerini tanımlıyorum. App Service modülündeki PrincipalId ve TenantId değerlerini bu modüle göndereceğim. Örnekte permissions için parametrik bir tanım yapmadım, ama isterseniz onu da parametrik yapabilirsiniz.
Resim-6
Modülleri tanımladım, şimdi sırada Azure CLI üzerinde çalıştıracağım asıl dosya olan main.bicep‘e geldi. Burada uzun bir parametre tanımı olacak, ama ilk olarak deployment yapacağımız scope değerini vermem gerekiyor. Yeni bir resource group oluşuracağım ve farklı bir resource group içerisinde yer alan Key vault’u kullanacağım için targetScope değerini subscription olarak belirliyorum. Burada çok parametre olmasının bir sebebi de birden fazla modüle göndereceğimiz parametrelerin birlikte yer alması. Ne kadar az hard-coded değer olursa, bizim için o kadar iyi. Burada da parametre değerlerine allowed ve min-max decorator’ları ile kısıtlamalar ekledim.
Resim-7
Şimdi de tanımlama kısımlarına sıra geldi. İlk olarak yeni oluşturacağım resource group tanımı ile başlıyorum. ResourceAbbreviation değerini birden fazla kez kullanacağım için, bunu bir değişken olarak tanımlıyorum, ihtiyaca göre parametre de olabilirdi.
Modül tanımı ise oldukça basit, resource yerine module keyword’ünü kullanıp, modülün olduğu dosyanın path’ini vermek yeterli. Sonrasında da modülde tanımlı parametreleri belirliyorum.
Resim-8
Resim-9‘da dikkatinizi çekmek istediğim diğer kısım ise dependsOn , yani modülün çalışması için önce hangi modüllerin çalışmış olması gerekliliği. App Service için App Service Plan varsayılan olarak gerekli olduğundan bu gibi durumlarda belirtmemize gerek yok, ama burada özellikle de Key vault access policies için yazmamız gerekiyor. App Service için yazmak zorunda değiliz, ama kodun okunabilirliği açısından yazmakta fayda olduğunu düşünüyorum.
Eğer daha önce bicep ile uğraştıysanız ya da internetteki diğer örneklere baktıysanız, App Service Config’te bir eksiklik olduğunu farkedeceksiniz. Secure olarak tanımladığım ve key vault’tan okuyacağım değerler için, key vault’un getSecret() methodu kullanılır. Böylece, deployment yapılırken istenilen değer, key vault’tan okunarak config’e yazılır. Buraya kadar her şey güzel, ama ben bun değerleri key vault’tan bir kere okuyup yazmak yerine, referans olarak eklemek istiyorum. Böylece App Service Config’e giren kişi, bu değerleri göremeyecek ve değerlerde bir değişiklik olursa tekrar buradan güncellemek zorunda kalmayacağım.
Resim-9
Ama referans olarak tanımlamak için, bu bilgiyi de tanımlamam gerekiyor. Burada da daha ikinci bölümde bahsettiğim parametre dosyasından faydalanacağım (Resim-10).
Resim-10
Bicep dosyaları tamamlandığına göre artık deployment komutunu çalıştırabilirim.
az deployment sub create –template-file main.bicep –parameter main.parameters.json -l uksouth
Deployment tamamlandıktan sonra Azure Portal üzerinden yeni oluşturduğum resource group’a giderek App Service, App Service Plan ve Application Insights kaynaklarını görebiliyorum (Resim-11).
Resim-11
App Service üzerinde Application settings’e geldiğimde ise, key vault referanslarını görebiliyorum. Eğer yetki ve erişim tanımları doğru bir şekilde yapılmadıysa, burada kırmızı hata işareti görecekseniz. Show value dediğinizde ise parametre dosyasında yer alan referans bilgisini göreceksiniz (Resim-12).
Resim-12
Son olarak da Application Insights enabled mı diye kontrol ediyorum (Resim-13).
Resim-13
Referanslar
Bicep documentation | Microsoft Docs
GitHub – mertyeter/bicep-samples
TAGs: Azure, Yazılım Geliştiriciler için Azure, Bicep, ARM Templates, JSON, Azure Resource Manager, IaC, Infrastructure as Code, VS Code, Visual Studio Code, Azure CLI, bicep nedir, bicep