Posted on Leave a comment

Push multiple docker container images using a loop – Azure DevOps

On a pipeline that I was creating I wanted to push multiple docker images on an Azure container registry based on a list. In order to do that I used the docker@2 task on a loop providing the images that I had to push as a parameter. Code is attached below.

trigger:
– none
pr: none
parameters:
– name: containerlist
type: object
default: ["core/image1","core/image2","core/image3","core/image4"]
– name: DockerPushID
type: string
pool:
name: demo-app
stages:
– stage: containers
displayName: Push containers to container registry $(registry)
jobs:
– job: pushcontainers
displayName: Push containers on testexample.azurecr.io
steps:
– checkout: none
– ${{ each container in parameters.containerlist }}:
– task: Docker@2
displayName: pushing image ${{container}}
inputs:
containerRegistry: 'registryconnection'
repository: '${{container}}'
command: 'push'
tags: |
current-${{parameters.DockerPushID}}
current-latest

This task will run steps based on the images you provide on the parameters list. An important note is that you need to have the image named accordingly in order to get a successful result. For example if you need to push on geralexgr.azurecr.io you will need to have your images named as below.

geralexgr.azurecr.io/image1:current-latest
geralexgr.azurecr.io/image2:current-latest

Else you may notice some failures indicating the below.

The push refers to repository [***/kati/image1] 
An image does not exist locally with the tag: ***/kati/image1

A successful run of the pipeline.

Additional information regarding loops and expressions on Azure DevOps pipelines:

https://docs.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devops#functions

Video tutorial on YouTube:

Posted on Leave a comment

Insert and retrieve data on Azure cosmos DB – C# SDK

Azure Cosmos DB is a database solution provided from Microsoft Azure that provides 99.999% SLA for enterprise level solutions.

In this article I will demonstrate how you can write a simple .NET application to insert and fetch data from a Cosmos DB.

First things first, you should have already a cosmos DB created. Then you will need to navigate in the keys section on Azure and retrieve your connection keys.

Using data explorer on Azure you can easily create new Databases and Containers. Containers are like Tables, but they also include other entities like Stored Procedures Triggers and User Defined Functions.

In my test I created a new Database named Data on which I created the table Locations. In this location table I wanted to append some location entries, that they will contain Longitude and Latitude.

That is why I created a class inside my Console App named Location

    public class Location
    {
        public Double Longtitude { get; set; }
        public Double Latitude { get; set; }
        [JsonProperty(PropertyName = "id")]
        public string Id { get; set; }
    }

My Program.cs is shown below:

using System;
using System.Threading.Tasks;
using System.Configuration;
using System.Collections.Generic;
using System.Net;
using Microsoft.Azure.Cosmos;
using cosmos;
using System.Timers;
public class Program
{
public static readonly string EndpointUri = "";
public static readonly string PrimaryKey = "";
public static CosmosClient cosmosClient;
public static Database database;
public static Container container;
static async Task Main(string[] args)
{
await GetStartedDemoAsync();
await QueryItemsAsync();
// insert test data with a timer.
//while(true)
//{
// await AddItemsToContainerAsync();
// Thread.Sleep(5000);
//}
}
private static async Task GetStartedDemoAsync()
{
var options = new CosmosClientOptions() { ConnectionMode = ConnectionMode.Gateway };
cosmosClient = new CosmosClient(EndpointUri, PrimaryKey,options);
database = cosmosClient.GetDatabase("Data");
container = database.GetContainer("Locations");
}
private static async Task AddItemsToContainerAsync()
{
cosmos.Location loc = new cosmos.Location
{
Latitude = 12.222222,
Longtitude = 15.555555,
Id = Guid.NewGuid().ToString()
};
ItemResponse<Location> loc_response = await container.CreateItemAsync<Location>( loc, new PartitionKey(loc.Id ));
Console.WriteLine("Created item in database with id: {0} Operation consumed {1} RUs.\n", loc_response.Resource, loc_response.RequestCharge);
}
private static async Task QueryItemsAsync()
{
var sqlQueryText = "SELECT * FROM Items";
QueryDefinition queryDefinition = new QueryDefinition(sqlQueryText);
FeedIterator<Location> queryResultSetIterator = container.GetItemQueryIterator<Location>(queryDefinition);
List<Location> mylist = new List<Location>();
while (queryResultSetIterator.HasMoreResults)
{
FeedResponse<Location> currentResultSet = await queryResultSetIterator.ReadNextAsync();
foreach (Location x in currentResultSet)
{
mylist.Add(x);
Console.WriteLine("\tRead {0}\n", x);
}
}
}
}

Key points of the implementation:

  • On the GetStartedDemoAsync the connection with the Cosmos DB is initialized using the connection strings and the database and container names. Its important to use the connectionMode Gateway because you will maybe face connection issues.
  • The function AddItemsToContainerAsync is used to insert values on the database. A common issue happens with the PartitionKey that is mandatory to be used on the CreateItemAsync function. In my case I use a random Guid value for it. You should define a JsonProperty on your model with the PartitionKey value and provide a value along with your data. On my Location loc constructor I append a new Guid as the Id value.
  • The QueryItemsAsync is used to retrieve the database values in a structure as your model.

The partition key is used to distribute your data into logical partition for scalability reasons. You should consider choosing an better value that is not random in order to take advantage of the Cosmos DB indexing engine.

Inside Task Main I used a while loop in order to insert some data on the cosmos DB database. As I do not have an external API source for the locations, the same location is added over and over again.

while(true)
{
await AddItemsToContainerAsync();
Thread.Sleep(5000);
}

Retrieving the values from the database.

Posted on Leave a comment

Create multiple environments with Terraform modules – App service Azure example

In this article I will demonstrate how one can create different environments for development needs through terraform modules. Modules provide great extensibility and code reuse. In this example I will use an appservice resource on Azure cloud.

The result of the deployment will be two different resource groups with two app services. The code of the demonstration is located at the bottom of the page.

You should first init your module. Navigate to the module folder and perform init

cd modules; terraform init
cd .. ; terraform init

Then validate your terraform code

terraform validate

The last step is to apply your configuration

terraform apply

You may encounter an error during the creation of the resources because of the app service name. It should be globally unique.

Change your name and perform a terraform apply again. Terraform will read your .tfstate file and will only implement the differences on infrastructure.

After the successful run you will see the green result output from terraform cli.

On Azure there should be two resource groups created. One for prod environment and one for test.

Inside each resource group there should be a different app service the one that it is created through the module according with the settings provided.

Production app service plan

GitHub repository:

https://github.com/geralexgr/terraform-module-environments-deploy

Video tutorial on YouTube: