Month: June 2018

Self-hosted TFS Linux Build agent for Docker – The type initializer for ‘system.net.http.curlhandler’ threw an exception

In the previous post that I demonstrated how to create a Self-hosted Build Agent on Windows. As I implemented Docker integration to the CI/CD DevOp pipeline on TFS, I need to make sure my build agent can build and push Docker image to Registry. The simple option is to installing Docker to our VM Windows Server, however, there are lots of issues to run Docker Windows on top of VM. I decided to create Linux VM for build agent and install Docker into it.

Following the same instructions to create build agent on Windows. The only issue is to run the config.sh on Linux, it throws an System.Net.Http.CurlHandler due to missing OpenSSL. The following approach can work for both Linux or MacOS.

brew update
brew install openssl
mkdir -p /usr/local/lib
sudo ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/
sudo ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/

then install the agent again

~/myagent$ ./config.sh

To run Agent as a Service:

sudo su
./svc.sh install
./svc.sh run

Then you just need to install Docker on Linux by using following commands.

sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable"
sudo apt-get update

apt-cache search docker-ce

sudo apt-get install docker-ce

Test if Docker is running with the following command

docker run hello-world

Permission issue when running docker with the build agent

Assign $USER to docker group
sudo usermod -a -G docker $USER
systemctl start docker
gpasswd -a $USER docker
reboot

** To build .NET Core application with Linux build, you need to install Java (for getting the source code) and .NET Core Sdk
wget -q https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get install dotnet-sdk-2.1

Install Java

sudo add-apt-repository ppa:webupd8team/java
sudo apt update; sudo apt install oracle-java8-installer

Posted by justinpham, 0 comments
Connect to MongoDB Atlas failed when using .NET Core running on Linux

Connect to MongoDB Atlas failed when using .NET Core running on Linux

I did an experiment on .NET Core Api connect to MongoDb Atlas, when I dockerize the Core Api, it works fine on Windows container and MacOS container. However, when I started deploy to Google Cloud, there is an exception throw from API

System.TimeoutException: A timeout occured after 30000ms selecting a server using CompositeServerSelector{ Selectors = WritableServerSelector, LatencyLimitingServerSelector{ AllowedLatencyRange = 00:00:00.0150000 } }. Client view of cluster state is { ClusterId : "1", ConnectionMode : "ReplicaSet", Type : "ReplicaSet", State : "Disconnected", Servers : [{ ServerId: "{ ClusterId : 1, EndPoint : "Unspecified/*****-shard-00-00-*****.mongodb.net:27017" }", EndPoint: "Unspecified/*****-shard-00-00-*****.mongodb.net:27017", State: "Disconnected", Type: "Unknown", HeartbeatException: "MongoDB.Driver.MongoConnectionException: An exception occurred while opening a connection to the server. ---> MongoDB.Driver.MongoCommandException: Command isMaster failed: no SNI name sent, make sure using a MongoDB 3.4+ driver/shell..
at MongoDB.Driver.Core.WireProtocol.CommandWireProtocol`1.ProcessReply(ConnectionId connectionId, ReplyMessage`1 reply)
at MongoDB.Driver.Core.WireProtocol.CommandWireProtocol`1.<ExecuteAsync>d__11.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MongoDB.Driver.Core.Connections.ConnectionInitializer.<InitializeConnectionAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MongoDB.Driver.Core.Connections.BinaryConnection.<OpenHelperAsync>d__48.MoveNext()
--- End of inner exception stack trace ---
at MongoDB.Driver.Core.Connections.BinaryConnection.<OpenHelperAsync>d__48.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MongoDB.Driver.Core.Servers.ServerMonitor.<HeartbeatAsync>d__27.MoveNext()" }, { ServerId: "{ ClusterId : 1, EndPoint : "Unspecified/*****-shard-00-01-*****.mongodb.net:27017" }", EndPoint: "Unspecified/*****-shard-00-01-*****.mongodb.net:27017", State: "Disconnected", Type: "Unknown", HeartbeatException: "MongoDB.Driver.MongoConnectionException: An exception occurred while opening a connection to the server. ---> MongoDB.Driver.MongoCommandException: Command isMaster failed: no SNI name sent, make sure using a MongoDB 3.4+ driver/shell..
at MongoDB.Driver.Core.WireProtocol.CommandWireProtocol`1.ProcessReply(ConnectionId connectionId, ReplyMessage`1 reply)
at MongoDB.Driver.Core.WireProtocol.CommandWireProtocol`1.<ExecuteAsync>d__11.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MongoDB.Driver.Core.Connections.ConnectionInitializer.<InitializeConnectionAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MongoDB.Driver.Core.Connections.BinaryConnection.<OpenHelperAsync>d__48.MoveNext()
--- End of inner exception stack trace ---
at MongoDB.Driver.Core.Connections.BinaryConnection.<OpenHelperAsync>d__48.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MongoDB.Driver.Core.Servers.ServerMonitor.<HeartbeatAsync>d__27.MoveNext()" }, { ServerId: "{ ClusterId : 1, EndPoint : "Unspecified/*****-shard-00-02-*****.mongodb.net:27017" }", EndPoint: "Unspecified/*****-shard-00-02-*****.mongodb.net:27017", State: "Disconnected", Type: "Unknown", HeartbeatException: "MongoDB.Driver.MongoConnectionException: An exception occurred while opening a connection to the server. ---> MongoDB.Driver.MongoCommandException: Command isMaster failed: no SNI name sent, make sure using a MongoDB 3.4+ driver/shell..
at MongoDB.Driver.Core.WireProtocol.CommandWireProtocol`1.ProcessReply(ConnectionId connectionId, ReplyMessage`1 reply)
at MongoDB.Driver.Core.WireProtocol.CommandWireProtocol`1.<ExecuteAsync>d__11.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MongoDB.Driver.Core.Connections.ConnectionInitializer.<InitializeConnectionAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MongoDB.Driver.Core.Connections.BinaryConnection.<OpenHelperAsync>d__48.MoveNext()
--- End of inner exception stack trace ---
at MongoDB.Driver.Core.Connections.BinaryConnection.<OpenHelperAsync>d__48.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MongoDB.Driver.Core.Servers.ServerMonitor.<HeartbeatAsync>d__27.MoveNext()" }] }.
at MongoDB.Driver.Core.Clusters.Cluster.ThrowTimeoutException(IServerSelector selector, ClusterDescription description)
at MongoDB.Driver.Core.Clusters.Cluster.WaitForDescriptionChangedHelper.HandleCompletedTask(Task completedTask)
at MongoDB.Driver.Core.Clusters.Cluster.WaitForDescriptionChanged(IServerSelector selector, ClusterDescription description, Task descriptionChangedTask, TimeSpan timeout, CancellationToken cancellationToken)
at MongoDB.Driver.Core.Clusters.Cluster.SelectServer(IServerSelector selector, CancellationToken cancellationToken)
at MongoDB.Driver.Core.Bindings.WritableServerBinding.GetWriteChannelSource(CancellationToken cancellationToken)
at MongoDB.Driver.Core.Operations.CreateIndexesOperation.Execute(IWriteBinding binding, CancellationToken cancellationToken)
at MongoDB.Driver.OperationExecutor.ExecuteWriteOperation[TResult](IWriteBinding binding, IWriteOperation`1 operation, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionImpl`1.ExecuteWriteOperation[TResult](IWriteOperation`1 operation, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionImpl`1.MongoIndexManager.CreateMany(IEnumerable`1 models, CancellationToken cancellationToken)
at MongoDB.Driver.MongoIndexManagerBase`1.CreateOne(IndexKeysDefinition`1 keys, CreateIndexOptions options, CancellationToken cancellationToken)

It’s a common error with C# Mongo Driver, because The .NET Core library 2.0 does not support the SNI TLS extension on Linux and OSX.

To fix the issue, I changed the base image on Dockerfile to microsoft/dotnet:2.1-aspnetcore-runtime. If you use Linux, use apt-get dotnet-runtime-2.1.

 

Posted by justinpham, 0 comments
Implement CI (Continuous Integration) – Create Build Agent to trigger build for .NET Core App

Implement CI (Continuous Integration) – Create Build Agent to trigger build for .NET Core App

Implement CI (Continuous Integration) – Create Build Agent to trigger build for .NET Core App

As we all know that CI is one of the process of Agile methodology to develop software faster by using smaller iteration sprint. The project that we develop with .NET Core to utilise the built-in DI and cross-platform support. Our source code hosted on TFS on-premise, so we need to create build agent with .NET Core support

Create Build Agent

To build or deploy your code, you need to have at least 1 build agent. If you already had build agent or using Microsoft-hosted agent from Visual Studio Team Services, you can skip this step. This step will show you how to create self-hosted build agent. You can view the agent pool to see if you already had build agent. The below screenshot shows that I already had a build agent

Let’s get started to create your first self-hosted build agent

Step 1. Login to your tfs server then create Personal Access Token by clicking to your profile and Click Security -> Add Personal Access Token and select scope as Agent Pool (manage, read). Keep the token in a safe place, you will need to use it later to create a new build agent. Then choose Download Agent. **You need to download agent to your TFS Server and follow instructions.

Step 2:

Open PowerShell and create agent folder
mkdir agent ; cd agent

Add-Type -AssemblyName System.IO.Compression.FileSystem ; [System.IO.Compression.ZipFile]::ExtractToDirectory("$HOME\Downloads\", "$PWD")

PS C:\agent> .\config.cmd

Step 3: 

Follow instructions to setup TFS Url – ** TFS Url needs to be a secured connection HTTPS to use PAT security method. When it prompts Access Token, use the Personal Access Token from Step 1. Once it all succeeds, new build agent will appear on Agent Pool

Posted by justinpham, 0 comments