From 4679da1c1e2755b4ee05657222f96face31f7e9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Cluseau?= Date: Wed, 9 Oct 2019 17:45:19 +1100 Subject: [PATCH] bootstrap pods support --- cmd/dkl-dir2config/render-cluster.go | 105 ++++++++++++++++++++------- cmd/dkl-dir2config/render-context.go | 29 ++------ cmd/dkl-local-server/ws.go | 6 ++ 3 files changed, 91 insertions(+), 49 deletions(-) diff --git a/cmd/dkl-dir2config/render-cluster.go b/cmd/dkl-dir2config/render-cluster.go index deb4ae6..7b3459c 100644 --- a/cmd/dkl-dir2config/render-cluster.go +++ b/cmd/dkl-dir2config/render-cluster.go @@ -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 { diff --git a/cmd/dkl-dir2config/render-context.go b/cmd/dkl-dir2config/render-context.go index a463563..9d33254 100644 --- a/cmd/dkl-dir2config/render-context.go +++ b/cmd/dkl-dir2config/render-context.go @@ -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{} { diff --git a/cmd/dkl-local-server/ws.go b/cmd/dkl-local-server/ws.go index e94aa65..e4969df 100644 --- a/cmd/dkl-local-server/ws.go +++ b/cmd/dkl-local-server/ws.go @@ -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).