manager/dedup.go
func (d *DedupManager) UpdateDeps(t *template.Template, deps []dep.Dependency) error {
	// Calculate the path to write updates to
	dataPath := path.Join(*d.config.Prefix, t.ID(), "data")

	// Package up the dependency data
	td := templateData{
		Version: version.Version,
		Data:    make(map[string]interface{}),
	}
	for _, dp := range deps {
		// Skip any dependencies that can't be shared
		if !dp.CanShare() {
			continue
		}

		// Pull the current value from the brain
		val, ok := d.brain.Recall(dp)
		if ok {
			td.Data[dp.String()] = val
		}
	}

	// Compute stable hash of the data. Note we don't compute this over the actual
	// encoded value since gob encoding does not guarantee stable ordering for
	// maps so spuriously returns a different hash most times. See
	// https://github.com/hashicorp/consul-template/issues/1099.
	hash, err := hashstructure.Hash(td, nil)
	if err != nil {
		return fmt.Errorf("calculating hash failed: %v", err)
	}
	d.lastWriteLock.RLock()
	existing, ok := d.lastWrite[t]
	d.lastWriteLock.RUnlock()
	if ok && existing == hash {
		log.Printf("[INFO] (dedup) de-duplicate data '%s' already current",
			dataPath)
		return nil
	}

	// Encode via GOB and LZW compress
	var buf bytes.Buffer
	compress := lzw.NewWriter(&buf, lzw.LSB, 8)
	enc := gob.NewEncoder(compress)
	if err := enc.Encode(&td); err != nil {
		return fmt.Errorf("encode failed: %v", err)
	}
	compress.Close()

	// Write the KV update
	kvPair := consulapi.KVPair{
		Key:   dataPath,
		Value: buf.Bytes(),
		Flags: templateDataFlag,
	}
	client := d.clients.Consul()
	if _, err := client.KV().Put(&kvPair, nil); err != nil {
		return fmt.Errorf("failed to write '%s': %v", dataPath, err)
	}
	log.Printf("[INFO] (dedup) updated de-duplicate data '%s'", dataPath)
	d.lastWriteLock.Lock()
	d.lastWrite[t] = hash
	d.lastWriteLock.Unlock()
	return nil
}
func (d *DedupManager) UpdateDeps(t *template.Template, deps []dep.Dependency) error {
	// Calculate the path to write updates to
	dataPath := path.Join(*d.config.Prefix, t.ID(), "data")

	// Package up the dependency data
	td := templateData{
		Version: version.Version,
		Data:    make(map[string]interface{}),
	}
	for _, dp := range deps {
		// Skip any dependencies that can't be shared
		if !dp.CanShare() {
			continue
		}

		// Pull the current value from the brain
		val, ok := d.brain.Recall(dp)
		if ok {
			td.Data[dp.String()] = val
		}
	}

	// Compute stable hash of the data. Note we don't compute this over the actual
	// encoded value since gob encoding does not guarantee stable ordering for
	// maps so spuriously returns a different hash most times. See
	// https://github.com/hashicorp/consul-template/issues/1099.
	hash, err := hashstructure.Hash(td, nil)
	if err != nil {
		return fmt.Errorf("calculating hash failed: %v", err)
	}
	d.lastWriteLock.RLock()
	existing, ok := d.lastWrite[t]
	d.lastWriteLock.RUnlock()
	if ok && existing == hash {
		log.Printf("[INFO] (dedup) de-duplicate data '%s' already current",
			dataPath)
		return nil
	}

	// Encode via GOB and LZW compress
	var buf bytes.Buffer
	compress := lzw.NewWriter(&buf, lzw.LSB, 8)
	enc := gob.NewEncoder(compress)
	if err := enc.Encode(&td); err != nil {
		return fmt.Errorf("encode failed: %v", err)
	}
	compress.Close()

	// Write the KV update
	kvPair := consulapi.KVPair{
		Key:   dataPath,
		Value: buf.Bytes(),
		Flags: templateDataFlag,
	}
	client := d.clients.Consul()
	if _, err := client.KV().Put(&kvPair, nil); err != nil {
		return fmt.Errorf("failed to write '%s': %v", dataPath, err)
	}
	log.Printf("[INFO] (dedup) updated de-duplicate data '%s'", dataPath)
	d.lastWriteLock.Lock()
	d.lastWrite[t] = hash
	d.lastWriteLock.Unlock()
	return nil
}
// UpdateDeps is used to update the values of the dependencies for a template