Vendor update to consul template 0.19.4
This commit is contained in:
parent
cb476f2f8c
commit
c60b7d45ed
|
@ -114,14 +114,19 @@ func (c *RetryConfig) RetryFunc() RetryFunc {
|
|||
return false, 0
|
||||
}
|
||||
|
||||
base := math.Pow(2, float64(retry))
|
||||
sleep := time.Duration(base) * TimeDurationVal(c.Backoff)
|
||||
|
||||
baseSleep := TimeDurationVal(c.Backoff)
|
||||
maxSleep := TimeDurationVal(c.MaxBackoff)
|
||||
if maxSleep > 0 && maxSleep < sleep {
|
||||
return true, maxSleep
|
||||
|
||||
if maxSleep > 0 {
|
||||
attemptsTillMaxBackoff := int(math.Log2(maxSleep.Seconds() / baseSleep.Seconds()))
|
||||
if retry > attemptsTillMaxBackoff {
|
||||
return true, maxSleep
|
||||
}
|
||||
}
|
||||
|
||||
base := math.Pow(2, float64(retry))
|
||||
sleep := time.Duration(base) * baseSleep
|
||||
|
||||
return true, sleep
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,11 +10,6 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
// DefaultTemplateFilePerms are the default file permissions for templates
|
||||
// rendered onto disk when a specific file permission has not already been
|
||||
// specified.
|
||||
DefaultTemplateFilePerms = 0644
|
||||
|
||||
// DefaultTemplateCommandTimeout is the amount of time to wait for a command
|
||||
// to return.
|
||||
DefaultTemplateCommandTimeout = 30 * time.Second
|
||||
|
@ -25,10 +20,6 @@ var (
|
|||
// are empty.
|
||||
ErrTemplateStringEmpty = errors.New("template: cannot be empty")
|
||||
|
||||
// ErrTemplateInvalidFormat is the error returned with the template is not
|
||||
// a valid format.
|
||||
ErrTemplateInvalidFormat = errors.New("template: invalid format")
|
||||
|
||||
// configTemplateRe is the pattern to split the config template syntax.
|
||||
configTemplateRe = regexp.MustCompile("([a-zA-Z]:)?([^:]+)")
|
||||
)
|
||||
|
@ -52,6 +43,10 @@ type TemplateConfig struct {
|
|||
// must be specified, but not both.
|
||||
Contents *string `mapstructure:"contents"`
|
||||
|
||||
// CreateDestDirs tells Consul Template to create the parent directories of
|
||||
// the destination path if they do not exist. The default value is true.
|
||||
CreateDestDirs *bool `mapstructure:"create_dest_dirs"`
|
||||
|
||||
// Destination is the location on disk where the template should be rendered.
|
||||
// This is required unless running in debug/dry mode.
|
||||
Destination *string `mapstructure:"destination"`
|
||||
|
@ -107,6 +102,8 @@ func (c *TemplateConfig) Copy() *TemplateConfig {
|
|||
|
||||
o.Contents = c.Contents
|
||||
|
||||
o.CreateDestDirs = c.CreateDestDirs
|
||||
|
||||
o.Destination = c.Destination
|
||||
|
||||
o.ErrMissingKey = c.ErrMissingKey
|
||||
|
@ -163,6 +160,10 @@ func (c *TemplateConfig) Merge(o *TemplateConfig) *TemplateConfig {
|
|||
r.Contents = o.Contents
|
||||
}
|
||||
|
||||
if o.CreateDestDirs != nil {
|
||||
r.CreateDestDirs = o.CreateDestDirs
|
||||
}
|
||||
|
||||
if o.Destination != nil {
|
||||
r.Destination = o.Destination
|
||||
}
|
||||
|
@ -217,6 +218,10 @@ func (c *TemplateConfig) Finalize() {
|
|||
c.Contents = String("")
|
||||
}
|
||||
|
||||
if c.CreateDestDirs == nil {
|
||||
c.CreateDestDirs = Bool(true)
|
||||
}
|
||||
|
||||
if c.Destination == nil {
|
||||
c.Destination = String("")
|
||||
}
|
||||
|
@ -239,7 +244,7 @@ func (c *TemplateConfig) Finalize() {
|
|||
c.Exec.Finalize()
|
||||
|
||||
if c.Perms == nil {
|
||||
c.Perms = FileMode(DefaultTemplateFilePerms)
|
||||
c.Perms = FileMode(0)
|
||||
}
|
||||
|
||||
if c.Source == nil {
|
||||
|
@ -271,6 +276,7 @@ func (c *TemplateConfig) GoString() string {
|
|||
"Command:%s, "+
|
||||
"CommandTimeout:%s, "+
|
||||
"Contents:%s, "+
|
||||
"CreateDestDirs:%s, "+
|
||||
"Destination:%s, "+
|
||||
"ErrMissingKey:%s, "+
|
||||
"Exec:%#v, "+
|
||||
|
@ -284,6 +290,7 @@ func (c *TemplateConfig) GoString() string {
|
|||
StringGoString(c.Command),
|
||||
TimeDurationGoString(c.CommandTimeout),
|
||||
StringGoString(c.Contents),
|
||||
BoolGoString(c.CreateDestDirs),
|
||||
StringGoString(c.Destination),
|
||||
BoolGoString(c.ErrMissingKey),
|
||||
c.Exec,
|
||||
|
@ -399,7 +406,8 @@ func ParseTemplateConfig(s string) (*TemplateConfig, error) {
|
|||
case 3:
|
||||
source, destination, command = parts[0], parts[1], parts[2]
|
||||
default:
|
||||
return nil, ErrTemplateInvalidFormat
|
||||
source, destination = parts[0], parts[1]
|
||||
command = strings.Join(parts[2:], ":")
|
||||
}
|
||||
|
||||
var sourcePtr, destinationPtr, commandPtr *string
|
||||
|
|
|
@ -16,7 +16,7 @@ var (
|
|||
_ Dependency = (*CatalogNodeQuery)(nil)
|
||||
|
||||
// CatalogNodeQueryRe is the regular expression to use.
|
||||
CatalogNodeQueryRe = regexp.MustCompile(`\A` + nameRe + dcRe + `\z`)
|
||||
CatalogNodeQueryRe = regexp.MustCompile(`\A` + nodeNameRe + dcRe + `\z`)
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -92,7 +92,11 @@ func (d *CatalogNodesQuery) Fetch(clients *ClientSet, opts *QueryOptions) (inter
|
|||
Meta: node.Meta,
|
||||
})
|
||||
}
|
||||
sort.Stable(ByNode(nodes))
|
||||
|
||||
// Sort unless the user explicitly asked for nearness
|
||||
if d.near == "" {
|
||||
sort.Stable(ByNode(nodes))
|
||||
}
|
||||
|
||||
rm := &ResponseMetadata{
|
||||
LastIndex: qm.LastIndex,
|
||||
|
|
|
@ -15,7 +15,7 @@ var (
|
|||
_ Dependency = (*CatalogServiceQuery)(nil)
|
||||
|
||||
// CatalogServiceQueryRe is the regular expression to use.
|
||||
CatalogServiceQueryRe = regexp.MustCompile(`\A` + tagRe + nameRe + dcRe + nearRe + `\z`)
|
||||
CatalogServiceQueryRe = regexp.MustCompile(`\A` + tagRe + serviceNameRe + dcRe + nearRe + `\z`)
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -310,7 +310,7 @@ func (c *ClientSet) Consul() *consulapi.Client {
|
|||
return c.consul.client
|
||||
}
|
||||
|
||||
// Vault returns the Consul client for this set.
|
||||
// Vault returns the Vault client for this set.
|
||||
func (c *ClientSet) Vault() *vaultapi.Client {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
|
|
|
@ -11,13 +11,14 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
dcRe = `(@(?P<dc>[[:word:]\.\-\_]+))?`
|
||||
keyRe = `/?(?P<key>[^@]+)`
|
||||
filterRe = `(\|(?P<filter>[[:word:]\,]+))?`
|
||||
nameRe = `(?P<name>[[:word:]\-\_]+)`
|
||||
nearRe = `(~(?P<near>[[:word:]\.\-\_]+))?`
|
||||
prefixRe = `/?(?P<prefix>[^@]+)`
|
||||
tagRe = `((?P<tag>[[:word:]\.\-\_]+)\.)?`
|
||||
dcRe = `(@(?P<dc>[[:word:]\.\-\_]+))?`
|
||||
keyRe = `/?(?P<key>[^@]+)`
|
||||
filterRe = `(\|(?P<filter>[[:word:]\,]+))?`
|
||||
serviceNameRe = `(?P<name>[[:word:]\-\_]+)`
|
||||
nodeNameRe = `(?P<name>[[:word:]\.\-\_]+)`
|
||||
nearRe = `(~(?P<near>[[:word:]\.\-\_]+))?`
|
||||
prefixRe = `/?(?P<prefix>[^@]+)`
|
||||
tagRe = `((?P<tag>[[:word:]\.\-\_]+)\.)?`
|
||||
)
|
||||
|
||||
type Type int
|
||||
|
|
|
@ -29,7 +29,7 @@ var (
|
|||
_ Dependency = (*HealthServiceQuery)(nil)
|
||||
|
||||
// HealthServiceQueryRe is the regular expression to use.
|
||||
HealthServiceQueryRe = regexp.MustCompile(`\A` + tagRe + nameRe + dcRe + nearRe + filterRe + `\z`)
|
||||
HealthServiceQueryRe = regexp.MustCompile(`\A` + tagRe + serviceNameRe + dcRe + nearRe + filterRe + `\z`)
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -174,7 +174,10 @@ func (d *HealthServiceQuery) Fetch(clients *ClientSet, opts *QueryOptions) (inte
|
|||
|
||||
log.Printf("[TRACE] %s: returned %d results after filtering", d, len(list))
|
||||
|
||||
sort.Stable(ByNodeThenID(list))
|
||||
// Sort unless the user explicitly asked for nearness
|
||||
if d.near == "" {
|
||||
sort.Stable(ByNodeThenID(list))
|
||||
}
|
||||
|
||||
rm := &ResponseMetadata{
|
||||
LastIndex: qm.LastIndex,
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/hashicorp/consul-template/config"
|
||||
dep "github.com/hashicorp/consul-template/dependency"
|
||||
"github.com/hashicorp/consul-template/template"
|
||||
"github.com/hashicorp/consul-template/version"
|
||||
consulapi "github.com/hashicorp/consul/api"
|
||||
)
|
||||
|
||||
|
@ -33,8 +34,14 @@ const (
|
|||
templateDataFlag = 0x22b9a127a2c03520
|
||||
)
|
||||
|
||||
// templateData is GOB encoded share the depdency values
|
||||
// templateData is GOB encoded share the dependency values
|
||||
type templateData struct {
|
||||
// Version is the version of Consul Template which created this template data.
|
||||
// This is important because users may be running multiple versions of CT
|
||||
// with the same templates. This provides a nicer upgrade path.
|
||||
Version string
|
||||
|
||||
// Data is the actual template data.
|
||||
Data map[string]interface{}
|
||||
}
|
||||
|
||||
|
@ -197,7 +204,8 @@ func (d *DedupManager) UpdateDeps(t *template.Template, deps []dep.Dependency) e
|
|||
|
||||
// Package up the dependency data
|
||||
td := templateData{
|
||||
Data: make(map[string]interface{}),
|
||||
Version: version.Version,
|
||||
Data: make(map[string]interface{}),
|
||||
}
|
||||
for _, dp := range deps {
|
||||
// Skip any dependencies that can't be shared
|
||||
|
@ -409,6 +417,11 @@ func (d *DedupManager) parseData(path string, raw []byte) {
|
|||
path, err)
|
||||
return
|
||||
}
|
||||
if td.Version != version.Version {
|
||||
log.Printf("[WARN] (dedup) created with different version (%s vs %s)",
|
||||
td.Version, version.Version)
|
||||
return
|
||||
}
|
||||
log.Printf("[INFO] (dedup) loading %d dependencies from '%s'",
|
||||
len(td.Data), path)
|
||||
|
||||
|
|
|
@ -11,14 +11,30 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultFilePerms are the default file permissions for files rendered onto
|
||||
// disk when a specific file permission has not already been specified.
|
||||
DefaultFilePerms = 0644
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNoParentDir is the error returned with the parent directory is missing
|
||||
// and the user disabled it.
|
||||
ErrNoParentDir = errors.New("parent directory is missing")
|
||||
|
||||
// ErrMissingDest is the error returned with the destination is empty.
|
||||
ErrMissingDest = errors.New("missing destination")
|
||||
)
|
||||
|
||||
// RenderInput is used as input to the render function.
|
||||
type RenderInput struct {
|
||||
Backup bool
|
||||
Contents []byte
|
||||
Dry bool
|
||||
DryStream io.Writer
|
||||
Path string
|
||||
Perms os.FileMode
|
||||
Backup bool
|
||||
Contents []byte
|
||||
CreateDestDirs bool
|
||||
Dry bool
|
||||
DryStream io.Writer
|
||||
Path string
|
||||
Perms os.FileMode
|
||||
}
|
||||
|
||||
// RenderResult is returned and stored. It contains the status of the render
|
||||
|
@ -58,7 +74,7 @@ func Render(i *RenderInput) (*RenderResult, error) {
|
|||
if i.Dry {
|
||||
fmt.Fprintf(i.DryStream, "> %s\n%s", i.Path, i.Contents)
|
||||
} else {
|
||||
if err := AtomicWrite(i.Path, i.Contents, i.Perms, i.Backup); err != nil {
|
||||
if err := AtomicWrite(i.Path, i.CreateDestDirs, i.Contents, i.Perms, i.Backup); err != nil {
|
||||
return nil, errors.Wrap(err, "failed writing file")
|
||||
}
|
||||
}
|
||||
|
@ -85,15 +101,19 @@ func Render(i *RenderInput) (*RenderResult, error) {
|
|||
//
|
||||
// If no errors occur, the Tempfile is "renamed" (moved) to the destination
|
||||
// path.
|
||||
func AtomicWrite(path string, contents []byte, perms os.FileMode, backup bool) error {
|
||||
func AtomicWrite(path string, createDestDirs bool, contents []byte, perms os.FileMode, backup bool) error {
|
||||
if path == "" {
|
||||
return fmt.Errorf("missing destination")
|
||||
return ErrMissingDest
|
||||
}
|
||||
|
||||
parent := filepath.Dir(path)
|
||||
if _, err := os.Stat(parent); os.IsNotExist(err) {
|
||||
if err := os.MkdirAll(parent, 0755); err != nil {
|
||||
return err
|
||||
if createDestDirs {
|
||||
if err := os.MkdirAll(parent, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return ErrNoParentDir
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,6 +135,22 @@ func AtomicWrite(path string, contents []byte, perms os.FileMode, backup bool) e
|
|||
return err
|
||||
}
|
||||
|
||||
// If the user did not explicitly set permissions, attempt to lookup the
|
||||
// current permissions on the file. If the file does not exist, fall back to
|
||||
// the default. Otherwise, inherit the current permissions.
|
||||
if perms == 0 {
|
||||
currentInfo, err := os.Stat(path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
perms = DefaultFilePerms
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
perms = currentInfo.Mode()
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.Chmod(f.Name(), perms); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -158,5 +194,10 @@ func copyFile(src, dst string) error {
|
|||
d.Close()
|
||||
return err
|
||||
}
|
||||
return d.Close()
|
||||
if err := d.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// io.Copy can restrict file permissions based on umask.
|
||||
return os.Chmod(dst, stat.Mode())
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ type Runner struct {
|
|||
|
||||
// outStream and errStream are the io.Writer streams where the runner will
|
||||
// write information. These can be modified by calling SetOutStream and
|
||||
// SetErrStream accordingly.
|
||||
// SetErrStream accordingly.
|
||||
|
||||
// inStream is the ioReader where the runner will read information.
|
||||
outStream, errStream io.Writer
|
||||
|
@ -740,12 +740,13 @@ func (r *Runner) runTemplate(tmpl *template.Template, runCtx *templateRunCtx) (*
|
|||
|
||||
// Render the template, taking dry mode into account
|
||||
result, err := Render(&RenderInput{
|
||||
Backup: config.BoolVal(templateConfig.Backup),
|
||||
Contents: result.Output,
|
||||
Dry: r.dry,
|
||||
DryStream: r.outStream,
|
||||
Path: config.StringVal(templateConfig.Destination),
|
||||
Perms: config.FileModeVal(templateConfig.Perms),
|
||||
Backup: config.BoolVal(templateConfig.Backup),
|
||||
Contents: result.Output,
|
||||
CreateDestDirs: config.BoolVal(templateConfig.CreateDestDirs),
|
||||
Dry: r.dry,
|
||||
DryStream: r.outStream,
|
||||
Path: config.StringVal(templateConfig.Destination),
|
||||
Perms: config.FileModeVal(templateConfig.Perms),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error rendering "+templateConfig.Display())
|
||||
|
@ -1252,14 +1253,14 @@ func newWatcher(c *config.Config, clients *dep.ClientSet, once bool) (*watch.Wat
|
|||
Clients: clients,
|
||||
MaxStale: config.TimeDurationVal(c.MaxStale),
|
||||
Once: once,
|
||||
RenewVault: config.StringPresent(c.Vault.Token) && config.BoolVal(c.Vault.RenewToken),
|
||||
RenewVault: clients.Vault().Token() != "" && config.BoolVal(c.Vault.RenewToken),
|
||||
RetryFuncConsul: watch.RetryFunc(c.Consul.Retry.RetryFunc()),
|
||||
// TODO: Add a sane default retry - right now this only affects "local"
|
||||
// dependencies like reading a file from disk.
|
||||
RetryFuncDefault: nil,
|
||||
RetryFuncVault: watch.RetryFunc(c.Vault.Retry.RetryFunc()),
|
||||
VaultGrace: config.TimeDurationVal(c.Vault.Grace),
|
||||
VaultToken: config.StringVal(c.Vault.Token),
|
||||
VaultToken: clients.Vault().Token(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "runner")
|
||||
|
|
|
@ -655,6 +655,25 @@ func in(l, v interface{}) (bool, error) {
|
|||
return false, nil
|
||||
}
|
||||
|
||||
// Indent prefixes each line of a string with the specified number of spaces
|
||||
func indent(spaces int, s string) (string, error) {
|
||||
var output, prefix []byte
|
||||
var sp bool
|
||||
var size int
|
||||
prefix = []byte(strings.Repeat(" ", spaces))
|
||||
sp = true
|
||||
for _, c := range []byte(s) {
|
||||
if sp && c != '\n' {
|
||||
output = append(output, prefix...)
|
||||
size += spaces
|
||||
}
|
||||
output = append(output, c)
|
||||
sp = c == '\n'
|
||||
size += 1
|
||||
}
|
||||
return string(output[:size]), nil
|
||||
}
|
||||
|
||||
// loop accepts varying parameters and differs its behavior. If given one
|
||||
// parameter, loop will return a goroutine that begins at 0 and loops until the
|
||||
// given int, increasing the index by 1 each iteration. If given two parameters,
|
||||
|
|
|
@ -233,6 +233,7 @@ func funcMap(i *funcMapInput) template.FuncMap {
|
|||
"executeTemplate": executeTemplateFunc(i.t),
|
||||
"explode": explode,
|
||||
"in": in,
|
||||
"indent": indent,
|
||||
"loop": loop,
|
||||
"join": join,
|
||||
"trimSpace": trimSpace,
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package version
|
||||
|
||||
import "fmt"
|
||||
|
||||
const Version = "0.19.5.dev"
|
||||
|
||||
var (
|
||||
Name string
|
||||
GitCommit string
|
||||
|
||||
HumanVersion = fmt.Sprintf("%s v%s (%s)", Name, Version, GitCommit)
|
||||
)
|
|
@ -709,44 +709,50 @@
|
|||
{
|
||||
"checksumSHA1": "Nu2j1GusM7ZH0uYrGzqr1K7yH7I=",
|
||||
"path": "github.com/hashicorp/consul-template/child",
|
||||
"revision": "16b6f8c417d88c88e9b88af6235da2582397c709",
|
||||
"revisionTime": "2017-10-03T21:31:50Z"
|
||||
"revision": "26d029ad37335b3827a9fde5569b2c5e10dcac8f",
|
||||
"revisionTime": "2017-10-31T14:25:17Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "nkbwT6jsnaXDiXrJFjCge9W5ULo=",
|
||||
"checksumSHA1": "qKAxyhYnUpKzZ5KpA6aOiIHHqqg=",
|
||||
"path": "github.com/hashicorp/consul-template/config",
|
||||
"revision": "16b6f8c417d88c88e9b88af6235da2582397c709",
|
||||
"revisionTime": "2017-10-03T21:31:50Z"
|
||||
"revision": "26d029ad37335b3827a9fde5569b2c5e10dcac8f",
|
||||
"revisionTime": "2017-10-31T14:25:17Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "ki5mjKALz3JrAee3mYUNl8pFJnU=",
|
||||
"checksumSHA1": "gZUb/+jEn+2hdO/lmQSKcYuOB/o=",
|
||||
"path": "github.com/hashicorp/consul-template/dependency",
|
||||
"revision": "16b6f8c417d88c88e9b88af6235da2582397c709",
|
||||
"revisionTime": "2017-10-03T21:31:50Z"
|
||||
"revision": "26d029ad37335b3827a9fde5569b2c5e10dcac8f",
|
||||
"revisionTime": "2017-10-31T14:25:17Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "yXXJXYYs/OPVJW2ErBiQVaLxSt0=",
|
||||
"checksumSHA1": "JVwx9FW1/nxRvg1lEeydBhaf3No=",
|
||||
"path": "github.com/hashicorp/consul-template/manager",
|
||||
"revision": "16b6f8c417d88c88e9b88af6235da2582397c709",
|
||||
"revisionTime": "2017-10-03T21:31:50Z"
|
||||
"revision": "26d029ad37335b3827a9fde5569b2c5e10dcac8f",
|
||||
"revisionTime": "2017-10-31T14:25:17Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "YSEUV/9/k85XciRKu0cngxdjZLE=",
|
||||
"path": "github.com/hashicorp/consul-template/signals",
|
||||
"revision": "16b6f8c417d88c88e9b88af6235da2582397c709",
|
||||
"revisionTime": "2017-10-03T21:31:50Z"
|
||||
"revision": "26d029ad37335b3827a9fde5569b2c5e10dcac8f",
|
||||
"revisionTime": "2017-10-31T14:25:17Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "zSvJlNfZS3fCRlFaZ7r9Q+N17T8=",
|
||||
"checksumSHA1": "N9qobVzScLbTEnGE7MgFnnTbGBw=",
|
||||
"path": "github.com/hashicorp/consul-template/template",
|
||||
"revision": "16b6f8c417d88c88e9b88af6235da2582397c709",
|
||||
"revisionTime": "2017-10-03T21:31:50Z"
|
||||
"revision": "26d029ad37335b3827a9fde5569b2c5e10dcac8f",
|
||||
"revisionTime": "2017-10-31T14:25:17Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "NB5+D4AuCNV9Bsqh3YFdPi4AJ6U=",
|
||||
"path": "github.com/hashicorp/consul-template/version",
|
||||
"revision": "26d029ad37335b3827a9fde5569b2c5e10dcac8f",
|
||||
"revisionTime": "2017-10-31T14:25:17Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "b4+Y+02pY2Y5620F9ALzKg8Zmdw=",
|
||||
"path": "github.com/hashicorp/consul-template/watch",
|
||||
"revision": "16b6f8c417d88c88e9b88af6235da2582397c709",
|
||||
"revisionTime": "2017-10-03T21:31:50Z"
|
||||
"revision": "26d029ad37335b3827a9fde5569b2c5e10dcac8f",
|
||||
"revisionTime": "2017-10-31T14:25:17Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "XLfcIX2qpRr0o26aFMjCOzvw6jo=",
|
||||
|
|
Loading…
Reference in New Issue