Browse Source

adding build numbers to terraform builds

master
forest 2 years ago
parent
commit
6d334e5a3b
  1. 1
      automation/terraformCodeGeneration.go
  2. 63
      automation/terraformSvg.go
  3. 2
      host-key-poller/main.go
  4. 36
      main.go
  5. 5
      terraform-modules/ansible-threshold-server/main.tf
  6. 1
      terraform-modules/gateway-instance-digitalocean/main.tf
  7. 2
      terraformStateHandler.go

1
automation/terraformCodeGeneration.go

@ -15,6 +15,7 @@ import (
)
type TerraformConfiguration struct {
BuildNumber int
TargetedModules []string
TerraformProject string
RemoteState string

63
automation/terraformSvg.go

@ -52,6 +52,8 @@ const terraformActionTextOffsetY = 5
const terraformActionOffsetY = 4
const terraformActionOffsetX = -4
const terraformActionTextSpacingX = 7
const dotStringCharactersMinPadding = 12
const dotStringLinearPadding = float32(0)
func (node *XMLNode) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
attrPointers := []*XMLAttr{}
@ -129,7 +131,7 @@ func makeSVGFromSimpleStatus(simpleStatus *SimplifiedTerraformStatus) ([]byte, e
}
resourceDot := fmt.Sprintf(`
"%s" [label = "%s"%s%s]`,
id, padStringForDot(resource.DisplayName, 0.1), tooltip, resourceStyle,
id, padStringForDot(resource.DisplayName), tooltip, resourceStyle,
)
resourceDots = append(resourceDots, resourceDot)
}
@ -156,7 +158,7 @@ func makeSVGFromSimpleStatus(simpleStatus *SimplifiedTerraformStatus) ([]byte, e
}`,
strings.ReplaceAll(strings.ReplaceAll(moduleName, ".", "_"), "-", "_"),
moduleName,
padStringForDot(moduleName, 0.1),
padStringForDot(moduleName),
strings.Join(resourceDots, ""),
)
//fmt.Println(moduleName)
@ -170,7 +172,7 @@ func makeSVGFromSimpleStatus(simpleStatus *SimplifiedTerraformStatus) ([]byte, e
variableDot := fmt.Sprintf(`
"%s" [label = "%s", tooltip = "%s", margin = 0.1, shape = "note"];`,
strings.ReplaceAll(strings.ReplaceAll(connection.From, ".", "_"), "-", "_"),
padStringForDot(remote_state_placeholder_text, 0.1),
padStringForDot(remote_state_placeholder_text),
connection.From,
)
variableDots = append(variableDots, variableDot)
@ -183,7 +185,7 @@ func makeSVGFromSimpleStatus(simpleStatus *SimplifiedTerraformStatus) ([]byte, e
if connectedVariables[variableName] {
variableDot := fmt.Sprintf(`
"var_%s" [label = "%s", tooltip = "%s", margin = 0.1, shape = "note"];`,
strings.ReplaceAll(variableName, "-", "_"), padStringForDot(value, 0.1), fmt.Sprintf("var.%s", variableName),
strings.ReplaceAll(variableName, "-", "_"), padStringForDot(value), fmt.Sprintf("var.%s", variableName),
)
variableDots = append(variableDots, variableDot)
}
@ -236,7 +238,7 @@ func makeSVGFromSimpleStatus(simpleStatus *SimplifiedTerraformStatus) ([]byte, e
}
connectionDot := fmt.Sprintf(`
"param_%s" [label = "%s", shape = "invhouse", style=filled, color=lightgrey]; %s %s`,
"param_%s" [label = "%s", shape = "box", style=filled, color=lightgrey]; %s %s`,
paramName, connection.DisplayName, sourceEdge, destEdge,
)
connectionDots = append(connectionDots, connectionDot)
@ -319,6 +321,37 @@ func makeSVGFromSimpleStatus(simpleStatus *SimplifiedTerraformStatus) ([]byte, e
}
if strings.HasPrefix(title, "param_") {
node.Parent.SetAttr("class", "parameter")
// the parameters start out as boxes
//but lets squeeze them into keystone shape to differentiate them a bit
node.Parent.WithQuerySelector([]XMLQuery{XMLQuery{NodeType: "polygon"}}, func(polygonNode *XMLNode) {
vertices, err := polygonNode.GetSVGPolygonVertices()
if err == nil {
center := []float64{0, 0}
for _, vertex := range vertices {
center[0] += vertex[0]
center[1] += vertex[1]
}
center[0] = center[0] / float64(len(vertices))
center[1] = center[1] / float64(len(vertices))
newVertices := [][]float64{}
for _, vertex := range vertices {
x := vertex[0]
y := vertex[1]
if y > center[1] {
if x > center[0] {
x -= 10
} else {
x += 10
}
}
newVertices = append(newVertices, []float64{x, y})
}
polygonNode.SetSVGPolygonVertices(newVertices)
}
})
}
if strings.HasPrefix(title, "module_") {
node.Parent.SetAttr("class", "resource")
@ -541,8 +574,8 @@ func makeSVGFromSimpleStatus(simpleStatus *SimplifiedTerraformStatus) ([]byte, e
return svgBytes, nil
}
func padStringForDot(str string, padAmount float32) string {
pad := strings.Repeat(" ", int(float32(len(str)+12)/(float32(1)/padAmount)))
func padStringForDot(str string) string {
pad := strings.Repeat(" ", int(float32(len(str)+dotStringCharactersMinPadding)*dotStringLinearPadding))
return fmt.Sprintf("%s%s%s", pad, str, pad)
}
@ -676,10 +709,10 @@ func (node *XMLNode) GetBoundingBox() *Rect2D {
ellipses := node.QuerySelectorAll([]XMLQuery{XMLQuery{NodeType: "ellipse"}})
for _, polygon := range polygons {
points, err := polygon.GetSVGPolygonPoints()
vertices, err := polygon.GetSVGPolygonVertices()
if err == nil {
for _, point := range points {
toReturn.Encapsulate(point[0], point[1])
for _, vertex := range vertices {
toReturn.Encapsulate(vertex[0], vertex[1])
}
}
}
@ -700,7 +733,7 @@ func (node *XMLNode) GetBoundingBox() *Rect2D {
return &toReturn
}
func (node *XMLNode) GetSVGPolygonPoints() ([][]float64, error) {
func (node *XMLNode) GetSVGPolygonVertices() ([][]float64, error) {
toReturn := [][]float64{}
var err error
@ -721,3 +754,11 @@ func (node *XMLNode) GetSVGPolygonPoints() ([][]float64, error) {
}
return toReturn, err
}
func (node *XMLNode) SetSVGPolygonVertices(points [][]float64) {
coordStrings := []string{}
for _, point := range points {
coordStrings = append(coordStrings, fmt.Sprintf("%.4f,%.4f", point[0], point[1]))
}
node.SetAttr("points", strings.Join(coordStrings, " "))
}

2
host-key-poller/main.go

@ -27,7 +27,7 @@ func main() {
}
iterations := 0
for iterations < 60 {
for iterations < 200 { // waits for a maximum of 200*5 seconds = 1000 seconds
iterations++
filename := fmt.Sprintf("rootsystem/known-hosts/%s", os.Args[1])

36
main.go

@ -5,6 +5,7 @@ import (
"fmt"
"log"
"net/http"
"strconv"
"strings"
errors "git.sequentialread.com/forest/pkg-errors"
@ -65,11 +66,31 @@ func main() {
panic(fmt.Sprintf("rootsystem can't start because can't create certs for threshold: %+v", err))
}
// Add 1 to the build number, each time rootsystem runs is a different build.
file, notFound, err := global.storage.Get("rootsystem/terraform-logs/build-number.txt")
if err != nil && !notFound {
panic(fmt.Sprintf("rootsystem can't start because can't download build-number.txt: %+v", err))
}
buildNumber := 1
if !notFound {
n, err := strconv.Atoi(string(file.Content))
if err != nil {
log.Printf("warning: build-number.txt did not contain a number. defaulting to build number 1. contents: %s\n", string(file.Content))
} else {
buildNumber = n + 1
}
}
err = global.storage.Put("rootsystem/terraform-logs/build-number.txt", []byte(strconv.Itoa(buildNumber)))
if err != nil {
panic(fmt.Sprintf("rootsystem can't start because can't upload build-number.txt: %+v", err))
}
// First, run the terraform build for the GLOBAL components, meaning the components
// that exist in the cloud, independent of how many server.garden nodes are being used.
outputVariables, success, err := terraformBuild(
config,
automation.TerraformConfiguration{
BuildNumber: buildNumber,
TargetedModules: config.Terraform.GlobalModules,
TerraformProject: configuration.GLOBAL_TERRAFORM_PROJECT,
HostKeysObjectStorageCredentials: knownHostsCredentials,
@ -90,6 +111,7 @@ func main() {
_, success, err = terraformBuild(
config,
automation.TerraformConfiguration{
BuildNumber: buildNumber,
TargetedModules: config.Terraform.LocalModules,
TerraformProject: projectName,
RemoteState: configuration.GLOBAL_TERRAFORM_PROJECT,
@ -132,7 +154,12 @@ func terraformBuild(
fmt.Println("TerraformPlanAndApply kicked off")
err = global.storage.Put(fmt.Sprintf("rootsystem/terraform/%s/diagram.svg", terraformConfig.TerraformProject), svg)
diagramPath := fmt.Sprintf(
"rootsystem/terraform-logs/%s/%d/diagram.svg",
terraformConfig.TerraformProject, terraformConfig.BuildNumber,
)
err = global.storage.Put(diagramPath, svg)
if err != nil {
return []string{}, false, err
}
@ -164,8 +191,11 @@ func terraformBuild(
// return []string{}, false, err
// }
// log.Println(string(statusJson1))
err = global.storage.Put(fmt.Sprintf("rootsystem/terraform/%s/status.json", terraformConfig.TerraformProject), statusJson)
statusPath := fmt.Sprintf(
"rootsystem/terraform-logs/%s/%d/status.json",
terraformConfig.TerraformProject, terraformConfig.BuildNumber,
)
err = global.storage.Put(statusPath, statusJson)
if err != nil {
log.Printf("can't upload terraform status update to object storage: %+v", err)
}

5
terraform-modules/ansible-threshold-server/main.tf

@ -19,6 +19,11 @@ variable "ingress_host_list" {
resource "null_resource" "ansible_playbook" {
count = length(var.ingress_host_list)
// things that trigger this playbook to run:
// - when the ingress host changes
// ( known_hosts_file_name is the name of the known-hosts file in object storage,
// which is unique to the cloud instance )
// - when the domain name changes
triggers = {
id = var.ingress_host_list[count.index].known_hosts_file_name
domain = var.domain_name

1
terraform-modules/gateway-instance-digitalocean/main.tf

@ -43,6 +43,7 @@ resource "null_resource" "host_key_poller" {
// we always want to run the host_key_poller because its possible that another instance created the
// gateway instance initially, so we might not have its host key added yet.
// host key poller runs quick so should be no problem
triggers = {
always_run = timestamp()
}

2
terraformStateHandler.go

@ -21,7 +21,7 @@ func (handler terraformStateHandler) ServeHTTP(response http.ResponseWriter, req
response.Write([]byte("file path cannot contain ."))
return
}
objectStoragePath := filepath.Join("/rootsystem/terraform", request.URL.Path, "terraform.tfstate")
objectStoragePath := filepath.Join("/rootsystem/terraform-state", request.URL.Path, "terraform.tfstate")
if request.Method == "GET" {
file, notFound, err := global.storage.Get(objectStoragePath)
if notFound {

Loading…
Cancel
Save