diff --git a/render-context.go b/render-context.go index 92df1b6..3774e63 100644 --- a/render-context.go +++ b/render-context.go @@ -66,6 +66,7 @@ func (ctx *renderContext) Config() (ba []byte, cfg *config.Config, err error) { ctxMap := ctx.asMap() + // FIXME duplicate sslCfg, err := cfsslconfig.LoadConfig([]byte(ctx.clusterConfig.SSLConfig)) if err != nil { return @@ -76,6 +77,76 @@ func (ctx *renderContext) Config() (ba []byte, cfg *config.Config, err error) { return } + extraFuncs := ctx.templateFuncs(secretData, ctxMap) + + extraFuncs["static_pods"] = func(name string) (string, error) { + t := ctx.clusterConfig.StaticPodsTemplate(name) + if t == nil { + return "", fmt.Errorf("no static pods template named %q", name) + } + + buf := &bytes.Buffer{} + err := t.Execute(buf, ctxMap, ctx.templateFuncs(secretData, ctxMap)) + if err != nil { + log.Printf("host %s: failed to render static pods: %v", ctx.Host.Name, err) + return "", err + } + + return buf.String(), nil + } + + buf := bytes.NewBuffer(make([]byte, 0, 4096)) + if err = ctx.ConfigTemplate.Execute(buf, ctxMap, extraFuncs); err != nil { + return + } + + if secretData.Changed() { + err = secretData.Save() + if err != nil { + return + } + } + + ba = buf.Bytes() + + cfg = &config.Config{} + + if err = yaml.Unmarshal(buf.Bytes(), cfg); err != nil { + return + } + + return +} + +func (ctx *renderContext) StaticPods() (ba []byte, err error) { + // FIXME duplicate + sslCfg, err := cfsslconfig.LoadConfig([]byte(ctx.clusterConfig.SSLConfig)) + if err != nil { + return + } + + secretData, err := loadSecretData(sslCfg) + if err != nil { + return + } + + if ctx.StaticPodsTemplate == nil { + err = notFoundError{fmt.Sprintf("static-pods %q", ctx.Group.StaticPods)} + return + } + + ctxMap := ctx.asMap() + + buf := bytes.NewBuffer(make([]byte, 0, 4096)) + if err = ctx.StaticPodsTemplate.Execute(buf, ctxMap, ctx.templateFuncs(secretData, ctxMap)); err != nil { + return + } + + ba = buf.Bytes() + return +} + +func (ctx *renderContext) templateFuncs(secretData *SecretData, ctxMap map[string]interface{}) map[string]interface{} { cluster := ctx.Cluster.Name getKeyCert := func(name string) (kc *KeyCert, err error) { @@ -122,23 +193,7 @@ func (ctx *renderContext) Config() (ba []byte, cfg *config.Config, err error) { return string(ba), nil } - extraFuncs := map[string]interface{}{ - "static_pods": func(name string) (string, error) { - t := ctx.clusterConfig.StaticPodsTemplate(name) - if t == nil { - return "", fmt.Errorf("no static pods template named %q", name) - } - - buf := &bytes.Buffer{} - err := t.Execute(buf, ctxMap, nil) - if err != nil { - log.Printf("host %s: failed to render static pods: %v", ctx.Host.Name, err) - return "", err - } - - return buf.String(), nil - }, - + return map[string]interface{}{ "token": func(name string) (s string, err error) { return secretData.Token(cluster, name) }, @@ -242,44 +297,32 @@ func (ctx *renderContext) Config() (ba []byte, cfg *config.Config, err error) { }, }) }, - } - buf := bytes.NewBuffer(make([]byte, 0, 4096)) - if err = ctx.ConfigTemplate.Execute(buf, ctxMap, extraFuncs); err != nil { - return - } + "hosts_of_group": func() (hosts []interface{}) { + hosts = make([]interface{}, 0) - if secretData.Changed() { - err = secretData.Save() - if err != nil { + for _, host := range ctx.clusterConfig.Hosts { + if host.Group != ctx.Host.Group { + continue + } + + hosts = append(hosts, asMap(host)) + } + + return hosts + }, + + "hosts_of_group_count": func() (count int) { + for _, host := range ctx.clusterConfig.Hosts { + if host.Group != ctx.Host.Group { + continue + } + + count++ + } return - } + }, } - - ba = buf.Bytes() - - cfg = &config.Config{} - - if err = yaml.Unmarshal(buf.Bytes(), cfg); err != nil { - return - } - - return -} - -func (ctx *renderContext) StaticPods() (ba []byte, err error) { - if ctx.StaticPodsTemplate == nil { - err = notFoundError{fmt.Sprintf("static-pods %q", ctx.Group.StaticPods)} - return - } - - buf := bytes.NewBuffer(make([]byte, 0, 4096)) - if err = ctx.StaticPodsTemplate.Execute(buf, ctx.asMap(), nil); err != nil { - return - } - - ba = buf.Bytes() - return } func (ctx *renderContext) distFilePath(path ...string) string { @@ -306,16 +349,7 @@ func (ctx *renderContext) Tag() (string, error) { } func (ctx *renderContext) asMap() map[string]interface{} { - ba, err := yaml.Marshal(ctx) - if err != nil { - panic(err) // shouldn't happen - } - - result := make(map[string]interface{}) - - if err := yaml.Unmarshal(ba, result); err != nil { - panic(err) - } + result := asMap(ctx) // also expand cluster: cluster := result["cluster"].(map[interface{}]interface{}) @@ -324,3 +358,18 @@ func (ctx *renderContext) asMap() map[string]interface{} { return result } + +func asMap(v interface{}) map[string]interface{} { + ba, err := yaml.Marshal(v) + if err != nil { + panic(err) // shouldn't happen + } + + result := make(map[string]interface{}) + + if err := yaml.Unmarshal(ba, result); err != nil { + panic(err) // shouldn't happen + } + + return result +}