github.com/dahs81/otto@v0.2.1-0.20160126165905-6400716cf085/helper/localaddr/db_cached.go (about)

     1  package localaddr
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"log"
     7  	"net"
     8  	"os"
     9  	"path/filepath"
    10  	"strings"
    11  
    12  	"github.com/hashicorp/otto/helper/oneline"
    13  )
    14  
    15  // CachedDB wraps a DB and caches the result of Next() into a local file,
    16  // reusing that for the duration that it exists (and automatically renewing
    17  // it).
    18  //
    19  // This is useful if you're consuming a single IP address and want a
    20  // consistent IP address across runs.
    21  type CachedDB struct {
    22  	// DB is the underlying DB to use
    23  	DB *DB
    24  
    25  	// CachePath is the path to a file that will store the cached IP.
    26  	CachePath string
    27  }
    28  
    29  // IP retrieves the IP address.
    30  //
    31  // If it is cached, it will renew and use that address. If it isn't cached,
    32  // then it will grab a new IP, cache that, and use that.
    33  func (db *CachedDB) IP() (net.IP, error) {
    34  	log.Printf("[DEBUG] reading IP, cache path: %s", db.CachePath)
    35  
    36  	// Try to read the cached version
    37  	_, err := os.Stat(db.CachePath)
    38  	if err == nil {
    39  		raw, err := oneline.Read(db.CachePath)
    40  		if err != nil {
    41  			return nil, err
    42  		}
    43  
    44  		ip := net.ParseIP(raw)
    45  		if ip != nil {
    46  			log.Printf("[DEBUG] read ip from cache: %s", ip)
    47  			db.DB.Renew(ip)
    48  			return ip, nil
    49  		}
    50  	}
    51  
    52  	// Make sure the directory to our cache path exists
    53  	if err := os.MkdirAll(filepath.Dir(db.CachePath), 0755); err != nil {
    54  		return nil, err
    55  	}
    56  
    57  	// No cached version.
    58  	log.Printf("[DEBUG] no ip cache found, getting new IP")
    59  	ip, err := db.DB.Next()
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  
    64  	contents := fmt.Sprintf(strings.TrimSpace(cacheContents)+"\n", ip.String())
    65  	err = ioutil.WriteFile(db.CachePath, []byte(contents), 0644)
    66  	if err != nil {
    67  		db.DB.Release(ip)
    68  		return nil, err
    69  	}
    70  
    71  	log.Printf("[DEBUG] new IP cached: %s", ip)
    72  	return ip, nil
    73  }
    74  
    75  const cacheContents = `
    76  %s
    77  
    78  DO NOT EDIT THIS FILE!
    79  
    80  The above is the IP address assigned to your development environment by
    81  Otto. Otto keeps careful track of used IP addresses and editing this file
    82  may corrupt its internal database of IP addresses.
    83  `