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 tasked with moving a web service across to Atlas. The data was simple to move (thanks to the migration tool), but we 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