bootstrap pods support

This commit is contained in:
Mikaël Cluseau 2019-10-09 17:45:19 +11:00
parent dde0ad6975
commit 4679da1c1e
3 changed files with 91 additions and 49 deletions

View File

@ -10,6 +10,49 @@ import (
"novit.nc/direktil/local-server/pkg/clustersconfig"
)
func clusterFuncs(clusterSpec *clustersconfig.Cluster) map[string]interface{} {
cluster := clusterSpec.Name
return map[string]interface{}{
"password": func(name string) (s string) {
return fmt.Sprintf("{{ password %q %q }}", cluster, name)
},
"token": func(name string) (s string) {
return fmt.Sprintf("{{ token %q %q }}", cluster, name)
},
"ca_key": func(name string) (s string, err error) {
// TODO check CA exists
// ?ctx.clusterConfig.CA(name)
return fmt.Sprintf("{{ ca_key %q %q }}", cluster, name), nil
},
"ca_crt": func(name string) (s string, err error) {
// TODO check CA exists
return fmt.Sprintf("{{ ca_crt %q %q }}", cluster, name), nil
},
"ca_dir": func(name string) (s string, err error) {
return fmt.Sprintf("{{ ca_dir %q %q }}", cluster, name), nil
},
"hosts_by_group": func(group string) (hosts []*clustersconfig.Host) {
for _, host := range src.Hosts {
if host.Group == group {
hosts = append(hosts, host)
}
}
if len(hosts) == 0 {
log.Fatalf("no hosts in group %q", group)
}
return
},
}
}
func renderClusterTemplates(cluster *clustersconfig.Cluster, setName string,
templates []*clustersconfig.Template) []byte {
clusterAsMap := asMap(cluster)
@ -20,7 +63,7 @@ func renderClusterTemplates(cluster *clustersconfig.Cluster, setName string,
for _, t := range templates {
fmt.Fprintf(buf, "---\n# %s: %s\n", setName, t.Name)
err := t.Execute(buf, clusterAsMap, nil)
err := t.Execute(buf, clusterAsMap, clusterFuncs(cluster))
if err != nil {
log.Fatalf("cluster %q: %s: failed to render %q: %v",
@ -63,33 +106,38 @@ func renderBootstrapPods(cluster *clustersconfig.Cluster) (pods []namePod) {
}
// render bootstrap pods
buf := bytes.NewBuffer(renderClusterTemplates(cluster, "bootstrap pods", bootstrapPods))
dec := yaml.NewDecoder(buf)
parts := bytes.Split(renderClusterTemplates(cluster, "bootstrap pods", bootstrapPods), []byte("\n---\n"))
for _, part := range parts {
buf := bytes.NewBuffer(part)
dec := yaml.NewDecoder(buf)
for n := 0; ; n++ {
podMap := map[string]interface{}{}
err := dec.Decode(podMap)
for n := 0; ; n++ {
str := buf.String()
if err == io.EOF {
break
} else if err != nil {
log.Fatalf("bootstrap pod %d: failed to parse: %v\n%s", n, err, buf.String())
podMap := map[string]interface{}{}
err := dec.Decode(podMap)
if err == io.EOF {
break
} else if err != nil {
log.Fatalf("bootstrap pod %d: failed to parse: %v\n%s", n, err, str)
}
if len(podMap) == 0 {
continue
}
if podMap["metadata"] == nil {
log.Fatalf("bootstrap pod %d: no metadata\n%s", n, buf.String())
}
md := podMap["metadata"].(map[interface{}]interface{})
namespace := md["namespace"].(string)
name := md["name"].(string)
pods = append(pods, namePod{namespace, name, podMap})
}
if len(podMap) == 0 {
continue
}
if podMap["metadata"] == nil {
log.Fatalf("bootstrap pod %d: no metadata\n%s", n, buf.String())
}
md := podMap["metadata"].(map[interface{}]interface{})
namespace := md["namespace"].(string)
name := md["name"].(string)
pods = append(pods, namePod{namespace, name, podMap})
}
return
@ -104,6 +152,13 @@ func renderBootstrapPodsDS(cluster *clustersconfig.Cluster) string {
md := pod["metadata"].(map[interface{}]interface{})
labels := md["labels"]
if labels == nil {
labels = map[string]interface{}{
"app": namePod.Name,
}
md["labels"] = labels
}
ann := md["annotations"]
annotations := map[interface{}]interface{}{}
if ann != nil {

View File

@ -198,30 +198,8 @@ func (ctx *renderContext) templateFuncs(ctxMap map[string]interface{}) map[strin
return
}
return map[string]interface{}{
"password": func(name string) (s string) {
return fmt.Sprintf("{{ password %q %q }}", cluster, name)
},
"token": func(name string) (s string) {
return fmt.Sprintf("{{ token %q %q }}", cluster, name)
},
"ca_key": func(name string) (s string, err error) {
// TODO check CA exists
// ?ctx.clusterConfig.CA(name)
return fmt.Sprintf("{{ ca_key %q %q }}", cluster, name), nil
},
"ca_crt": func(name string) (s string, err error) {
// TODO check CA exists
return fmt.Sprintf("{{ ca_crt %q %q }}", cluster, name), nil
},
"ca_dir": func(name string) (s string, err error) {
return fmt.Sprintf("{{ ca_dir %q %q }}", cluster, name), nil
},
funcs := clusterFuncs(ctx.Cluster)
for k, v := range map[string]interface{}{
"tls_key": func(name string) (string, error) {
return getKeyCert(name, "tls_key")
},
@ -256,7 +234,10 @@ func (ctx *renderContext) templateFuncs(ctxMap map[string]interface{}) map[strin
}
return
},
} {
funcs[k] = v
}
return funcs
}
func (ctx *renderContext) asMap() map[string]interface{} {

View File

@ -34,6 +34,12 @@ func registerWS(rest *restful.Container) {
Returns(http.StatusOK, "OK", nil).
Returns(http.StatusNotFound, "The cluster does not exists or does not have addons defined", nil))
ws.Route(ws.GET("/clusters/{cluster-name}/bootstrap-pods").To(wsClusterBootstrapPods).
Produces(mime.YAML).
Doc("Get cluster bootstrap pods YAML definitions").
Returns(http.StatusOK, "OK", nil).
Returns(http.StatusNotFound, "The cluster does not exists or does not have bootstrap pods defined", nil))
ws.Route(ws.GET("/clusters/{cluster-name}/passwords").To(wsClusterPasswords).
Doc("List cluster's passwords"))
ws.Route(ws.GET("/clusters/{cluster-name}/passwords/{password-name}").To(wsClusterPassword).