server.garden privileged automation agent (mirror of https://git.sequentialread.com/forest/rootsystem)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

165 lines
4.7 KiB

package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"git.sequentialread.com/forest/rootsystem/automation"
"git.sequentialread.com/forest/rootsystem/configuration"
"git.sequentialread.com/forest/rootsystem/objectStorage"
)
type applicationState struct {
workingDirectory string
storage objectStorage.ObjectStorager
}
var global applicationState
// func main() {
// config, workingDirectory, err := configuration.LoadConfiguration()
// if err != nil {
// panic(errors.Wrap(err, "rootsystem can't start because loadConfiguration() returned"))
// }
// global.workingDirectory = workingDirectory
// storage, err := objectStorage.InitializeObjectStorage(config, true)
// if err != nil {
// panic(errors.Wrap(err, "rootsystem can't start because failed to initialize object storage"))
// }
// global.storage = storage
// go terraformStateServer()
// // This creates an access key that the gateway cloud instance can use to upload its SSH public key
// // to our object storage. the host-key-poller will download this SSH host public key and add it to our known_hosts
// // so that we can SSH to the gateway instance securely
// hostKeysAccessSpec := objectStorage.ObjectStorageKey{
// Name: "rootsystem-known-hosts",
// PathPrefix: "rootsystem/known-hosts",
// Read: true,
// Write: true,
// Delete: false,
// List: false,
// }
// knownHostsCredentials, err := global.storage.CreateAccessKeyIfNotExists(hostKeysAccessSpec)
// if err != nil {
// panic(err)
// }
// // BuildTLSCertsForThreshold fills in the CAs, Keys, and Certificates in the Threshold ansible roles.
// // So when terraform invokes ansible to install threshold client/server, it will install working
// // certificates and keys
// err = pki.BuildTLSCertsForThreshold(
// global.workingDirectory,
// config.Terraform.Variables["domain_name"],
// config.Host.Name,
// global.storage,
// )
// if err != nil {
// panic(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, err := terraformBuild(
// config,
// automation.TerraformConfiguration{
// TargetedModules: config.Terraform.GlobalModules,
// TerraformProject: configuration.GLOBAL_TERRAFORM_PROJECT,
// HostKeysObjectStorageCredentials: knownHostsCredentials,
// },
// )
// if err != nil {
// panic(err)
// }
// os.Exit(0)
// // Next, we run a separate LOCAL terraform build which is specific to THIS server.garden node,
// // this build will be responsible for installing software on this node & registering this node with the
// // cloud resources
// _, err = terraformBuild(
// config,
// automation.TerraformConfiguration{
// TargetedModules: config.Terraform.LocalModules,
// TerraformProject: fmt.Sprintf("%s-%s", configuration.LOCAL_TERRAFORM_PROJECT, config.Host.Name),
// RemoteState: configuration.GLOBAL_TERRAFORM_PROJECT,
// RemoteStateVariables: outputVariables,
// },
// )
// if err != nil {
// panic(err)
// }
// a := make(chan bool)
// <-a
// }
func terraformBuild(
config *configuration.Configuration,
terraformConfig automation.TerraformConfiguration,
) ([]string, error) {
outputVariables, err := automation.WriteTerraformCodeForTargetedModules(
config,
global.workingDirectory,
terraformConfig,
)
if err != nil {
return []string{}, err
}
fmt.Println("WriteTerraformCodeForTargetedModules done")
svg, statusChannel, err := automation.TerraformPlanAndApply(config, global.workingDirectory, terraformConfig.TerraformProject)
if err != nil {
return []string{}, err
}
fmt.Println("TerraformPlanAndApply done")
err = global.storage.Put("rootsystem/terraform/diagram.svg", []byte(svg))
if err != nil {
return []string{}, err
}
var terraformPlanAndApplyError error = nil
for status := range statusChannel {
json, err := json.MarshalIndent(status, "", " ")
if err != nil {
return []string{}, err
}
log.Println(status.Log)
err = global.storage.Put("rootsystem/terraform/status.json", []byte(json))
if err != nil {
return []string{}, err
}
if status.Complete {
terraformPlanAndApplyError = status.Error
}
}
if terraformPlanAndApplyError != nil {
return outputVariables, terraformPlanAndApplyError
}
return outputVariables, nil
}
func terraformStateServer() error {
// Make sure to only listen on localhost.
// TODO change this to HTTPS or unix socket
server := http.Server{
Addr: fmt.Sprintf("127.0.0.1:%d", configuration.TERRAFORM_STATE_SERVER_PORT_NUMBER),
Handler: terraformStateHandler{},
}
return server.ListenAndServe()
}