Connect to Mongo Atlas with Go

mongo atlas drawing

With the recent closure of mLab and the simple migration tool across to their successor, Mongo Atlas, I’ve recently been moving a web service across to Atlas. The data was simple to move (thanks to the migration tool), but I had to change the code to handle this new connection. The service is written in Go (as in golang) and I wanted to give an example of how to connect to Atlas - as it was a little different from connecting to mLab.

In our example below, we’re using the mgo driver, so it will be a little different to using the official Mongo driver. The key changes in the code when using Atlas over mlab include:

  • Requiring a TLS connection
  • Having multiple hosts (due to shards)
  • A different auth database (admin vs. the owner’s db)
package main

import (
	"crypto/tls"
	"errors"
	"fmt"
	"log"
	"net"
	"net/url"
	"strings"
	"time"

	"github.com/globalsign/mgo"
)

var mongoSession *mgo.Session

func main() {
	var err error
	mongoSession, err = makeMongoSession()
	if err != nil {
		log.Fatal(err)
	}
	// Try connection
	if err := mongoSession.Ping(); err != nil {
		log.Fatal(err)
	} else {
		fmt.Println("Connection Established to Mongo")
	}
}

func makeMongoSession() (*mgo.Session, error) {

	// Our connection string - would be an environment variable most likely
	// Note: we changed the host to the first shard
	mongoURI := "mongodb+srv://mongouser:mongopass@cluster-shard-00-00.mfv6x.mongodb.net:27017/dbname"

	parts, err := url.Parse(mongoURI)
	if err != nil {
		return nil, err
	}
	password, isSet := parts.User.Password()
	if !isSet {
		return nil, errors.New("Error parsing Mongo password (env var)")
	}

	// Build our list of hosts (currently set to 3)
	mongoHost := []string{
		parts.Host,
		strings.ReplaceAll(parts.Host, "00-00", "00-01"),
		strings.ReplaceAll(parts.Host, "00-00", "00-02"),
	}

	dialInfo := mgo.DialInfo{
		Addrs:    mongoHost,
		Timeout:  15 * time.Second,
		Database: strings.ReplaceAll(parts.Path, "/", ""),
		Username: parts.User.Username(),
		Password: password,
		Source:   "admin", // auth db
	}
	// Connect with TLS
	tlsConfig := &tls.Config{}
	dialInfo.DialServer = func(addr *mgo.ServerAddr) (net.Conn, error) {
		conn, err := tls.Dial("tcp", addr.String(), tlsConfig) // add TLS config
		return conn, err
	}
	return mgo.DialWithInfo(&dialInfo)
}

example of connection to mongo atlas with go