Skip to content

Commit

Permalink
Refactored runbook creation step for testing
Browse files Browse the repository at this point in the history
  • Loading branch information
mcasperson committed Jul 22, 2024
1 parent c62a5bc commit 7a389d2
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 153 deletions.
309 changes: 158 additions & 151 deletions internal/steps/project_export.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package steps
import (
"bytes"
_ "embed"
"errors"
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
Expand Down Expand Up @@ -77,203 +78,209 @@ func (s ProjectExportStep) createNewProject(parent fyne.Window) {
s.createProject.Disable()
s.result.SetText("🔵 Creating runbooks. This can take a little while.")

go func() {
defer s.previous.Enable()
defer s.infinite.Hide()
defer s.createProject.Enable()
s.Execute(func(title string, message string, callback func(bool)) {
dialog.NewConfirm(title, message, callback, parent).Show()
}, func(message string, err error) {
s.result.SetText(message)
s.logs.SetText(err.Error())
s.previous.Enable()
s.infinite.Hide()
s.createProject.Enable()
}, func(message string) {
s.result.SetText(message)
s.previous.Enable()
s.infinite.Hide()
s.createProject.Enable()
})
}

myclient, err := octoclient.CreateClient(s.State)
func (s ProjectExportStep) Execute(prompt func(string, string, func(bool)), handleError func(string, error), handleSuccess func(string)) {
defer s.previous.Enable()
defer s.infinite.Hide()
defer s.createProject.Enable()

if err != nil {
s.logs.SetText("🔴 Failed to create the client:\n" + err.Error())
return
}
myclient, err := octoclient.CreateClient(s.State)

allProjects, err := s.getProjects(myclient)
if err != nil {
handleError("🔴 Failed to create the client", err)
return
}

if err != nil {
s.logs.SetText("🔴 Failed to get all the projects:\n" + err.Error())
return
}
allProjects, err := s.getProjects(myclient)

allProjects = lo.Filter(allProjects, func(project *projects.Project, index int) bool {
return project.Name != spaceManagementProject
})
if err != nil {
handleError("🔴 Failed to get all the projects", err)
return
}

lvsExists, lvs, err := query.LibraryVariableSetExists(myclient)
allProjects = lo.Filter(allProjects, func(project *projects.Project, index int) bool {
return project.Name != spaceManagementProject
})

if err != nil {
s.logs.SetText("🔴 Failed to get the library variable set Octoterra:\n" + err.Error())
return
lvsExists, lvs, err := query.LibraryVariableSetExists(myclient)

if err != nil {
handleError("🔴 Failed to get the library variable set Octoterra", err)
return
}

if !lvsExists {
handleError("🔴 The library variable set Octoterra could not be found", errors.New("resource not found"))
return
}

// First look deletes any existing projects
for _, project := range allProjects {
if project.Name == spaceManagementProject {
continue
}

if !lvsExists {
s.logs.SetText("🔴 The library variable set Octoterra could not be found")
runbookExists, runbook, err := s.runbookExists(myclient, project.ID, "__ 1. Serialize Project")

if err != nil {
handleError("🔴 Failed to find runbook", err)
return
}

// First look deletes any existing projects
for _, project := range allProjects {
if project.Name == spaceManagementProject {
continue
if runbookExists {
deleteRunbook1Func := func(b bool) {
if b {
if err := s.deleteRunbook(myclient, runbook); err != nil {
s.result.SetText("🔴 Failed to delete the resource")
s.logs.SetText(err.Error())
} else if s.State.PromptForDelete {
s.Execute(prompt, handleError, handleSuccess)
}
}
}

runbookExists, runbook, err := s.runbookExists(myclient, project.ID, "__ 1. Serialize Project")

if err != nil {
s.logs.SetText("🔴 Failed to find runbook:\n" + err.Error())
if s.State.PromptForDelete {
prompt("Project Group Exists", "The runbook \""+runbook.Name+"\" already exists in project "+project.Name+". Do you want to delete it? It is usually safe to delete this resource.", deleteRunbook1Func)
return
} else {
deleteRunbook1Func(true)
}
}

if runbookExists {
deleteRunbook1Func := func(b bool) {
if b {
if err := s.deleteRunbook(myclient, runbook); err != nil {
s.result.SetText("🔴 Failed to delete the resource")
s.logs.SetText(err.Error())
} else if s.State.PromptForDelete {
s.createNewProject(parent)
}
}
}
runbook2Exists, runbook2, err := s.runbookExists(myclient, project.ID, "__ 2. Deploy Project")

if s.State.PromptForDelete {
dialog.NewConfirm("Project Group Exists", "The runbook \""+runbook.Name+"\" already exists in project "+project.Name+". Do you want to delete it? It is usually safe to delete this resource.", deleteRunbook1Func, parent).Show()
if err != nil {
handleError("🔴 Failed to find runbook", err)
return
}

// We can't go further until the resource is deleted
return
} else {
deleteRunbook1Func(true)
if runbook2Exists {
deleteRunbook2Func := func(b bool) {
if b {
if err := s.deleteRunbook(myclient, runbook2); err != nil {
s.result.SetText("🔴 Failed to delete the resource")
s.logs.SetText(err.Error())
} else if s.State.PromptForDelete {
s.Execute(prompt, handleError, handleSuccess)
}
}
}

runbook2Exists, runbook2, err := s.runbookExists(myclient, project.ID, "__ 2. Deploy Project")

if err != nil {
s.logs.SetText("🔴 Failed to find runbook:\n" + err.Error())
if s.State.PromptForDelete {
prompt("Project Group Exists", "The runbook \""+runbook2.Name+"\" already exists in project "+project.Name+". Do you want to delete it? It is usually safe to delete this resource.", deleteRunbook2Func)
return
} else {
deleteRunbook2Func(true)
}
}
}

if runbook2Exists {
deleteRunbook2Func := func(b bool) {
if b {
if err := s.deleteRunbook(myclient, runbook2); err != nil {
s.result.SetText("🔴 Failed to delete the resource")
s.logs.SetText(err.Error())
} else if s.State.PromptForDelete {
s.createNewProject(parent)
}
}
}
// Find the step template ID
serializeProjectTemplate, err, message := query.GetStepTemplateId(myclient, s.State, "Octopus - Serialize Project to Terraform")

if s.State.PromptForDelete {
dialog.NewConfirm("Project Group Exists", "The runbook \""+runbook2.Name+"\" already exists in project "+project.Name+". Do you want to delete it? It is usually safe to delete this resource.", deleteRunbook2Func, parent).Show()
// We can't go further until the resource is deleted
return
} else {
deleteRunbook2Func(true)
}
}
}
if err != nil {
handleError(message, err)
return
}

// Find the step template ID
serializeProjectTemplate, err, message := query.GetStepTemplateId(myclient, s.State, "Octopus - Serialize Project to Terraform")
deploySpaceTemplateS3, err, message := query.GetStepTemplateId(myclient, s.State, "Octopus - Populate Octoterra Space (S3 Backend)")

if err != nil {
handleError(message, err)
return
}

for index, project := range allProjects {
// Save and apply the module
dir, err := ioutil.TempDir("", "octoterra")
if err != nil {
s.result.SetText(message)
s.logs.SetText(err.Error())
handleError("An error occurred while creating a temporary directory", err)
return
}

deploySpaceTemplateS3, err, message := query.GetStepTemplateId(myclient, s.State, "Octopus - Populate Octoterra Space (S3 Backend)")
filePath := filepath.Join(dir, "terraform.tf")

if err != nil {
s.result.SetText(message)
s.logs.SetText(err.Error())
if err := os.WriteFile(filePath, []byte(runbookModule), 0644); err != nil {
handleError("🔴 An error occurred while writing the Terraform file", err)
return
}

for index, project := range allProjects {
// Save and apply the module
dir, err := ioutil.TempDir("", "octoterra")
if err != nil {
s.logs.SetText("An error occurred while creating a temporary directory:\n" + err.Error())
return
}

filePath := filepath.Join(dir, "terraform.tf")

if err := os.WriteFile(filePath, []byte(runbookModule), 0644); err != nil {
s.logs.SetText("🔴 An error occurred while writing the Terraform file:\n" + err.Error())
return
}
initCmd := exec.Command("terraform", "init", "-no-color")
initCmd.Dir = dir

initCmd := exec.Command("terraform", "init", "-no-color")
initCmd.Dir = dir

var initStdout, initStderr bytes.Buffer
initCmd.Stdout = &initStdout
initCmd.Stderr = &initStderr

if err := initCmd.Run(); err != nil {
s.result.SetText("🔴 Terraform init failed.")
s.logs.SetText(initStdout.String() + initCmd.String())
return
}
var initStdout, initStderr bytes.Buffer
initCmd.Stdout = &initStdout
initCmd.Stderr = &initStderr

applyCmd := exec.Command("terraform",
"apply",
"-auto-approve",
"-no-color",
"-var=octopus_serialize_actiontemplateid="+serializeProjectTemplate,
"-var=octopus_deploys3_actiontemplateid="+deploySpaceTemplateS3,
"-var=octopus_server="+s.State.Server,
"-var=octopus_apikey="+s.State.ApiKey,
"-var=octopus_space_id="+s.State.Space,
"-var=octopus_project_id="+project.ID,
"-var=terraform_state_bucket="+s.State.AwsS3Bucket,
"-var=terraform_state_bucket_region="+s.State.AwsS3BucketRegion,
"-var=octopus_destination_server="+s.State.DestinationServer,
"-var=octopus_destination_apikey="+s.State.DestinationApiKey,
"-var=octopus_destination_space_id="+s.State.DestinationSpace,
"-var=octopus_project_name="+project.Name)
applyCmd.Dir = dir

var stdout, stderr bytes.Buffer
applyCmd.Stdout = &stdout
applyCmd.Stderr = &stderr

if err := applyCmd.Run(); err != nil {
s.result.SetText("🔴 Terraform apply failed")
s.logs.SetText(stdout.String() + stderr.String())
return
} else {
s.result.SetText("🔵 Terraform apply succeeded (" + fmt.Sprint(index) + " / " + fmt.Sprint(len(allProjects)) + ")")
s.logs.SetText(stdout.String() + stderr.String())
}
if err := initCmd.Run(); err != nil {
handleError("🔴 Terraform init failed.", errors.New(initStdout.String()+initCmd.String()))
return
}

// link the library variable set
project, err := myclient.Projects.GetByID(project.ID)
applyCmd := exec.Command("terraform",
"apply",
"-auto-approve",
"-no-color",
"-var=octopus_serialize_actiontemplateid="+serializeProjectTemplate,
"-var=octopus_deploys3_actiontemplateid="+deploySpaceTemplateS3,
"-var=octopus_server="+s.State.Server,
"-var=octopus_apikey="+s.State.ApiKey,
"-var=octopus_space_id="+s.State.Space,
"-var=octopus_project_id="+project.ID,
"-var=terraform_state_bucket="+s.State.AwsS3Bucket,
"-var=terraform_state_bucket_region="+s.State.AwsS3BucketRegion,
"-var=octopus_destination_server="+s.State.DestinationServer,
"-var=octopus_destination_apikey="+s.State.DestinationApiKey,
"-var=octopus_destination_space_id="+s.State.DestinationSpace,
"-var=octopus_project_name="+project.Name)
applyCmd.Dir = dir

var stdout, stderr bytes.Buffer
applyCmd.Stdout = &stdout
applyCmd.Stderr = &stderr

if err := applyCmd.Run(); err != nil {
handleError("🔴 Terraform apply failed", errors.New(stdout.String()+stderr.String()))
return
} else {
handleSuccess("🔵 Terraform apply succeeded (" + fmt.Sprint(index) + " / " + fmt.Sprint(len(allProjects)) + ")")
}

if err != nil {
s.logs.SetText("🔴 Failed to get the project:\n" + err.Error())
return
}
// link the library variable set
project, err := myclient.Projects.GetByID(project.ID)

project.IncludedLibraryVariableSets = append(project.IncludedLibraryVariableSets, lvs.ID)
if err != nil {
handleError("🔴 Failed to get the project", err)
return
}

_, err = projects.Update(myclient, project)
project.IncludedLibraryVariableSets = append(project.IncludedLibraryVariableSets, lvs.ID)

if err != nil {
s.logs.SetText("🔴 Failed to update the project:\n" + err.Error())
return
}
_, err = projects.Update(myclient, project)

if err != nil {
handleError("🔴 Failed to update the project", err)
return
}

s.result.SetText("🟢 Added runbooks to all projects")
s.next.Enable()
}()
}

handleSuccess("🟢 Added runbooks to all projects")
}

func (s ProjectExportStep) getProjects(myclient *client.Client) ([]*projects.Project, error) {
Expand Down
4 changes: 2 additions & 2 deletions internal/steps/space_export.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,15 @@ func (s SpaceExportStep) GetContainer(parent fyne.Window) *fyne.Container {
s.logs.Disable()
s.logs.MultiLine = true
s.logs.SetMinRowsVisible(20)
s.createProject = widget.NewButton("Create Project", func() { s.createNewProject(parent, false, false) })
s.createProject = widget.NewButton("Create Project", func() { s.createNewProject(parent) })
middle := container.New(layout.NewVBoxLayout(), intro, s.createProject, s.infinite, s.result, s.logs)

content := container.NewBorder(nil, bottom, nil, nil, middle)

return content
}

func (s SpaceExportStep) createNewProject(parent fyne.Window, attemptedLvsDelete bool, attemptedAccountDelete bool) {
func (s SpaceExportStep) createNewProject(parent fyne.Window) {
s.logs.SetText("")
s.next.Disable()
s.previous.Disable()
Expand Down

0 comments on commit 7a389d2

Please sign in to comment.