add plattform services

This commit is contained in:
Marcel Arndt
2026-01-05 16:01:40 +01:00
parent e25d8dd5d9
commit 193319fa52
65 changed files with 4240 additions and 39 deletions
+3
View File
@@ -0,0 +1,3 @@
config:
hcloud:token:
secure: AAABAHkvxBXaEbrikY6bNyuwXehFp71LvsHTT2LOYHLiAaRCil5cSODn1EktYTYL+f4ryGJtN1j/wiyrAkbZBnyVC1QnSb84tTLYeKYXBtHo2fY87vReuyOwFZbFGylC
+9
View File
@@ -0,0 +1,9 @@
name: gc-infra
description: A minimal Go Pulumi program
runtime: go
config:
pulumi:tags:
value:
pulumi:template: go
# hcloud:token:
# value: xqb89P4vF2YlBjU75AAtyoQzNvTHaXyhB0J2UYR8dAmEQDKz5GWeKO7KgEyPzUu5
+35 -28
View File
@@ -16,7 +16,7 @@ import (
type Infrastructure struct {
placementGroup *hcloud.PlacementGroup
networkID *pulumi.IDOutput
masterNodes []*hcloud.Server
managerNodes []*hcloud.Server
workerNodes []*hcloud.Server
}
@@ -55,30 +55,31 @@ func main() {
panic(err.Error())
}
infra.masterNodes, err = utils.CreateServer(ctx, utils.CreateServerArgs{
infra.managerNodes, err = utils.CreateServer(ctx, utils.CreateServerArgs{
PlacementGroupId: infra.placementGroup.ID(),
NetworkId: infra.networkID,
NetworkFirstIP: string(utils.IncrementIP(net.ParseIP("10.0.1.0"))),
Basename: "master-node",
Count: 1,
SshKey: hkey,
})
if err != nil {
panic(err.Error())
}
infra.workerNodes, err = utils.CreateServer(ctx, utils.CreateServerArgs{
PlacementGroupId: infra.placementGroup.ID(),
NetworkId: infra.networkID,
NetworkFirstIP: string(utils.IncrementIP(net.ParseIP("10.0.1.20"))),
Basename: "worker-node",
Count: 2,
Basename: "manager-node",
Count: 3,
SshKey: hkey,
ServerType: "ccx23",
})
if err != nil {
panic(err.Error())
}
// infra.workerNodes, err = utils.CreateServer(ctx, utils.CreateServerArgs{
// PlacementGroupId: infra.placementGroup.ID(),
// NetworkId: infra.networkID,
// NetworkFirstIP: string(utils.IncrementIP(net.ParseIP("10.0.1.20"))),
// Basename: "worker-node",
// Count: 2,
// SshKey: hkey,
// })
// if err != nil {
// panic(err.Error())
// }
for idx, s := range slices.Concat(infra.masterNodes, infra.workerNodes) {
for idx, s := range slices.Concat(infra.managerNodes, infra.workerNodes) {
err := utils.InstallAnsibleDependencies(ctx, remote.ConnectionArgs{
Host: s.Ipv4Address,
User: pulumi.String("root"),
@@ -89,22 +90,28 @@ func main() {
}
}
var advAddr = infra.masterNodes[0].Networks.ApplyT(func(net []hcloud.ServerNetworkType) string {
return *net[0].Ip
}).(pulumi.StringOutput)
// var advAddr = infra.managerNodes[0].Networks.ApplyT(func(net []hcloud.ServerNetworkType) string {
// return *net[0].Ip
// }).(pulumi.StringOutput)
tokens, err := utils.InitDockerSwarm(ctx, remote.ConnectionArgs{
Host: infra.masterNodes[0].Ipv4Address,
User: pulumi.String("root"),
PrivateKey: pk.PrivateKeyOpenssh}, advAddr)
if err != nil {
panic(err.Error())
}
// tokens, err := utils.InitDockerSwarm(ctx, remote.ConnectionArgs{
// Host: infra.managerNodes[0].Ipv4Address,
// User: pulumi.String("root"),
// PrivateKey: pk.PrivateKeyOpenssh}, advAddr)
// if err != nil {
// panic(err.Error())
// }
ctx.Export("SwarmTokens", tokens)
// ctx.Export("SwarmTokens", tokens)
// inventory, err := utils.CreateAnsibleInventory(infra.managerNodes, infra.workerNodes)
// if err != nil {
// panic(err.Error())
// }
// ctx.Export("inventory", inventory)
sm := map[string]pulumi.Input{}
for idx, s := range slices.Concat(infra.masterNodes, infra.workerNodes) {
for idx, s := range slices.Concat(infra.managerNodes, infra.workerNodes) {
sm[fmt.Sprintf("node-%d-ip", idx)] = s.Ipv4Address
}
ctx.Export("server-ips", pulumi.Map(sm))
+102 -8
View File
@@ -1,11 +1,14 @@
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"
)
@@ -14,6 +17,11 @@ type SwarmJoinTokens struct {
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{
@@ -26,7 +34,7 @@ func InstallAnsibleDependencies(ctx *pulumi.Context, connArgs remote.ConnectionA
return nil
}
func InitDockerSwarm(ctx *pulumi.Context, connArgs remote.ConnectionArgs, advertiseAddr pulumi.StringOutput) (pulumi.StringOutput, error) {
func InitDockerSwarm(ctx *pulumi.Context, connArgs remote.ConnectionArgs, advertiseAddr pulumi.StringOutput) (pulumi.Output, error) {
var tokens SwarmJoinTokens
fullCommand := advertiseAddr.ApplyT(func(addr string) *string {
@@ -44,17 +52,103 @@ func InitDockerSwarm(ctx *pulumi.Context, connArgs remote.ConnectionArgs, advert
return pulumi.StringOutput{}, err
}
return out.Stdout.ApplyT(func(output string) string {
return out.Stdout.ApplyT(func(output string) SwarmJoinTokens {
searchWorker := "Worker Token: "
pattern := regexp.MustCompile(searchWorker + `(\S+)`)
patternWorker := regexp.MustCompile(searchWorker + `(\S+)`)
searchManager := "Manager Token: "
patternManager := regexp.MustCompile(searchManager + `(\S+)`)
matches := pattern.FindStringSubmatch(output)
matches := patternWorker.FindStringSubmatch(output)
if len(matches) > 1 {
extracted := matches[1]
tokens.WorkerToken = extracted
return extracted
}
fmt.Println(tokens.WorkerToken)
return ""
}).(pulumi.StringOutput), nil
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
}
+21 -3
View File
@@ -54,6 +54,7 @@ type CreateServerArgs struct {
Basename string
Count int
SshKey *hcloud.SshKey
ServerType string
}
func CreateServer(ctx *pulumi.Context, cfg CreateServerArgs) ([]*hcloud.Server, error) {
@@ -64,9 +65,8 @@ func CreateServer(ctx *pulumi.Context, cfg CreateServerArgs) ([]*hcloud.Server,
s, err := hcloud.NewServer(ctx, sn, &hcloud.ServerArgs{
Name: pulumi.String(sn),
Image: pulumi.String("docker-ce"),
ServerType: pulumi.String("cpx21"),
Location: pulumi.StringPtr("fsn1"),
// Datacenter: pulumi.StringPtr("fsn1"),
ServerType: pulumi.String(cfg.ServerType),
Location: pulumi.StringPtr("hel1"),
Networks: hcloud.ServerNetworkTypeArray{
&hcloud.ServerNetworkTypeArgs{
NetworkId: IDtoIntOutput(cfg.NetworkId),
@@ -85,6 +85,24 @@ func CreateServer(ctx *pulumi.Context, cfg CreateServerArgs) ([]*hcloud.Server,
if err != nil {
return nodes, err
}
cephVolume, err := hcloud.NewVolume(ctx, fmt.Sprintf("ceph-%s", sn), &hcloud.VolumeArgs{
Name: pulumi.Sprintf("%s-ceph-vol-0%d", s.Name, i+1),
Size: pulumi.Int(100),
Location: s.Location,
})
if err != nil {
return nodes, fmt.Errorf("couldn't create volume: %w", err)
}
_, err = hcloud.NewVolumeAttachment(ctx, fmt.Sprintf("ceph-vol-attach-%s", sn), &hcloud.VolumeAttachmentArgs{
VolumeId: IDtoIntOutput(cephVolume.ID()),
ServerId: IDtoIntOutput(s.ID()),
})
if err != nil {
return nodes, fmt.Errorf("couldn't attach volume to node %d", i)
}
nodes = append(nodes, s)
nextIp = IncrementIP(net.ParseIP(nextIp)).String()
}