155 lines
4.5 KiB
Go
155 lines
4.5 KiB
Go
package utils
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
"text/template"
|
|
|
|
"github.com/pulumi/pulumi-command/sdk/go/command/remote"
|
|
"github.com/pulumi/pulumi-hcloud/sdk/go/hcloud"
|
|
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
|
|
)
|
|
|
|
type SwarmJoinTokens struct {
|
|
ManagerToken string
|
|
WorkerToken string
|
|
}
|
|
|
|
type ServerInfo struct {
|
|
Name pulumi.StringOutput
|
|
IP pulumi.StringOutput
|
|
}
|
|
|
|
func InstallAnsibleDependencies(ctx *pulumi.Context, connArgs remote.ConnectionArgs, uniqueness string) error {
|
|
_, err := remote.NewCommand(ctx, strings.Join([]string{uniqueness, "Install Ansible Dependencies"}, ": "),
|
|
&remote.CommandArgs{
|
|
Connection: connArgs,
|
|
Create: pulumi.String("apt-get update && apt-get install -y python3-pip python3-jsondiff"),
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func InitDockerSwarm(ctx *pulumi.Context, connArgs remote.ConnectionArgs, advertiseAddr pulumi.StringOutput) (pulumi.Output, error) {
|
|
var tokens SwarmJoinTokens
|
|
|
|
fullCommand := advertiseAddr.ApplyT(func(addr string) *string {
|
|
initCommand := fmt.Sprintf("docker swarm init --advertise-addr %s", addr)
|
|
fullCommand := strings.Join([]string{initCommand, "echo \"Manager Token: $(docker swarm join-token -q manager)\"", "echo \"Worker Token: $(docker swarm join-token -q worker)\""}, " && ")
|
|
return &fullCommand
|
|
}).(pulumi.StringPtrOutput)
|
|
|
|
out, err := remote.NewCommand(ctx, "Init docker swarm",
|
|
&remote.CommandArgs{
|
|
Connection: connArgs,
|
|
Create: fullCommand,
|
|
})
|
|
if err != nil {
|
|
return pulumi.StringOutput{}, err
|
|
}
|
|
|
|
return out.Stdout.ApplyT(func(output string) SwarmJoinTokens {
|
|
searchWorker := "Worker Token: "
|
|
patternWorker := regexp.MustCompile(searchWorker + `(\S+)`)
|
|
searchManager := "Manager Token: "
|
|
patternManager := regexp.MustCompile(searchManager + `(\S+)`)
|
|
|
|
matches := patternWorker.FindStringSubmatch(output)
|
|
if len(matches) > 1 {
|
|
extracted := matches[1]
|
|
tokens.WorkerToken = extracted
|
|
}
|
|
matches = patternManager.FindStringSubmatch(output)
|
|
if len(matches) > 1 {
|
|
extracted := matches[1]
|
|
tokens.ManagerToken = extracted
|
|
}
|
|
return tokens
|
|
}), nil
|
|
}
|
|
|
|
func CreateAnsibleInventory(managerNodes, workerNodes []*hcloud.Server) (pulumi.Output, error) {
|
|
serverInfos := toServerInfo(managerNodes)
|
|
return pulumi.All(pulumi.ToOutput(serverInfos)).ApplyT(func(results []interface{}) (string, error) {
|
|
var serverInfos = results[0].([]ServerInfo)
|
|
// var workerSlice = results[1].([]*hcloud.Server)
|
|
|
|
serverData := make(map[string][]ServerInfo)
|
|
|
|
for _, s := range serverInfos {
|
|
serverData["Manager"] = append(serverData["Manager"], ServerInfo{
|
|
Name: s.Name,
|
|
IP: s.IP,
|
|
})
|
|
}
|
|
// for _, result := range workerSlice {
|
|
// server := result.(map[string]interface{})
|
|
// serverData["Worker"] = append(serverData["Worker"], ServerInfo{
|
|
// Name: server["name"].(string),
|
|
// IP: server["ipv4_address"].(string),
|
|
// })
|
|
// }
|
|
fmt.Println(serverData["Manager"])
|
|
fmt.Println(results[0])
|
|
return generateInventoryFile(serverData)
|
|
}).(pulumi.Output), nil
|
|
}
|
|
|
|
func toServerInfo(server []*hcloud.Server) pulumi.ArrayOutput {
|
|
serverInfo := []ServerInfo{}
|
|
for _, s := range server {
|
|
serverInfo = append(serverInfo, ServerInfo{
|
|
Name: s.Name,
|
|
IP: s.Ipv4Address,
|
|
})
|
|
}
|
|
return pulumi.All(serverInfo).ApplyT(func(args []interface{}) []interface{} {
|
|
var serverInfo []interface{}
|
|
|
|
for _, s := range args {
|
|
val := s.(map[string]interface{})
|
|
serverInfo = append(serverInfo, map[string]interface{}{
|
|
"Name": val["Name"].(string),
|
|
"IP": val["IP"].(string),
|
|
})
|
|
}
|
|
return serverInfo
|
|
}).(pulumi.ArrayOutput)
|
|
}
|
|
|
|
func generateInventoryFile(inventory map[string][]ServerInfo) (string, error) {
|
|
const inventoryTmpl = `
|
|
[all]
|
|
{{ range .Manager }}
|
|
{{ .Name }} ansible_host={{ .IP }} ansible_connection=ssh ansible_user=root ansible_ssh_private_key_file=../infra-base/private_key
|
|
{{ end }}
|
|
{{ range .Worker }}
|
|
{{ .Name }} ansible_host={{ .IP }} ansible_connection=ssh ansible_user=root ansible_ssh_private_key_file=../infra-base/private_key
|
|
{{ end }}
|
|
|
|
[manager]
|
|
{{ range .Manager }}
|
|
{{ .Name }} ansible_host={{ .IP }} ansible_connection=ssh ansible_user=root ansible_ssh_private_key_file=../infra-base/private_key
|
|
{{ end }}
|
|
|
|
[worker]
|
|
{{ range .Worker }}
|
|
{{ .Name }} ansible_host={{ .IP }} ansible_connection=ssh ansible_user=root ansible_ssh_private_key_file=../infra-base/private_key
|
|
{{ end }}
|
|
`
|
|
tmpl, err := template.New("inventory").Parse(inventoryTmpl)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
var buf bytes.Buffer
|
|
err = tmpl.Execute(&buf, inventory)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return buf.String(), nil
|
|
}
|