Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 52 additions & 37 deletions foreman-builder/cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,6 @@ import (
"github.com/spf13/cobra"
)

type opts struct {
choices []string
cursor int
selected map[int]struct{}
}

func initialOpts() opts {
return opts{
choices: []string{"bash", "zsh"},
selected: make(map[int]struct{}),
}
}

var createCmd = &cobra.Command{
Use: "create",
Short: "Create a new container environment",
Expand All @@ -34,6 +21,8 @@ var createCmd = &cobra.Command{
},
}

var containerType = "orb"

func runCreate() {
currentUser, err := user.Current()
if err != nil {
Expand All @@ -50,64 +39,90 @@ func runCreate() {
containerName = "foreman"
}

// p := tea.NewProgram(initialOpts())
// finalOpts, err := p.Run()
// if err != nil {
// fmt.Printf("Alas, there's been an error: %v", err)
// os.Exit(1)
// }
// m := finalOpts.(opts)
home, err := os.UserHomeDir()
if err != nil {
foremanbuilder.Logger.Fatalf("Failed to get home directory: %v", err)
}

// currently will not do anything
// selectedShell := m.choices[m.cursor]
containerNameExists, err := foremanbuilder.GetLineInFile(filepath.Join(home, ".foreman-builder/containers"), containerName, "")
if err != nil {
if err.Error() != "not_found" {
fmt.Println("An Error has occured searching dotfile")
os.Exit(1)
}
}
foremanbuilder.Logger.Debug("container name: %s \n", containerName)
foremanbuilder.Logger.Debug("container name EXISTS: %s \n", containerNameExists)
if containerNameExists != "" {
fmt.Println("Container name must be unique")
os.Exit(1)
}

// fmt.Println("Selected Shell", selectedShell)
err = foremanbuilder.AppendToFile(filepath.Join(home, ".foreman-builder/containers"), fmt.Sprintf("%s::%s", containerName, containerType))
if err != nil {
foremanbuilder.Logger.Error("Failed to write container to container file")
}

foremanbuilder.Logger.Info("Starting environment creation")

if containerType == "orb" {
orbOpts := foremanbuilder.OrbOptions{
Username: username,
ContainerName: containerName,
}
err := createOrbstackContainer(orbOpts)
if err != nil {
// better error message to show?
fmt.Println("An error has occured during container creation")
os.Exit(1)
}
}

}

func createOrbstackContainer(opts foremanbuilder.OrbOptions) error {
config, err := foremanbuilder.GetYmlValues("./config.yml")
if err != nil {
foremanbuilder.Logger.Info("No config file found, skipping")
}

data := foremanbuilder.OrbstackConfigData{
Username: username,
Username: opts.Username,
Packages: config.Packages,
}

// check for errors by doing ssh <container-name>@orb cat /var/log/cloud-init-output.log

home, err := os.UserHomeDir()
if err != nil {
foremanbuilder.Logger.Fatalf("Failed to get home directory: %v", err)
foremanbuilder.Logger.Errorf("Failed to get home directory: %v", err)
return err
}

confsDir := filepath.Join(home, ".foreman-builder", "confs")
if err := os.MkdirAll(confsDir, 0755); err != nil {
foremanbuilder.Logger.Fatalf("Failed to create confs directory: %v", err)
foremanbuilder.Logger.Errorf("Failed to create confs directory: %v", err)
return err
}

pathName := filepath.Join(confsDir, fmt.Sprintf("orbstack-foreman-%s.yml", data.Username))
fmt.Println("using", pathName)
foremanbuilder.Logger.Info("using", pathName)
err = foremanbuilder.GenerateContainerConfig(data, pathName)
if err != nil {
foremanbuilder.Logger.Fatal(err)
foremanbuilder.Logger.Errorf("failed to generate container config, err : %v\n", err)
return err
}

// run command to create container
orbArgs := []string{"create", "-a", "amd64", "-c", pathName, "rocky:9", containerName}
fmt.Println("running: orb", strings.Join(orbArgs, " "))
orbArgs := []string{"create", "-a", "amd64", "-c", pathName, "rocky:9", opts.ContainerName}
foremanbuilder.Logger.Info("running: orb", strings.Join(orbArgs, " "))
cmd := exec.Command("orb", orbArgs...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
foremanbuilder.Logger.Fatalf("Error creating container: %s", err)
foremanbuilder.Logger.Errorf("Error creating container: %s", err)
return err
}
fmt.Println("Container has been created!")

err = foremanbuilder.AppendToFile(filepath.Join(home, ".foreman-builder/containers"), containerName)
if err != nil {
foremanbuilder.Logger.Error("Failed to write container to container file")
}
return nil

}
25 changes: 19 additions & 6 deletions foreman-builder/cmd/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os/exec"
"path/filepath"
"slices"
"strings"

foremanbuilder "github.com/aidenfine/foreman-builder/foreman-builder"
"github.com/spf13/cobra"
Expand All @@ -21,7 +22,7 @@ var deleteCmd = &cobra.Command{
os.Exit(1)
}
containerName := args[0]
runDelete(containerName)
runDelete(fmt.Sprint(strings.Split(containerName, "::")[0]))

},
}
Expand All @@ -35,7 +36,9 @@ func runDelete(containerName string) {
}
dotFolderPath := filepath.Join(home, ".foreman-builder")
containersPath := filepath.Join(dotFolderPath, "containers")
containers, err := foremanbuilder.GetAllLines(containersPath)
containers, err := foremanbuilder.GetAllLines(containersPath, "::")
foremanbuilder.Logger.Debugf("containers: %v\n", containers)
foremanbuilder.Logger.Debugf("containerName: %s \n", containerName)

if !slices.Contains(containers, containerName) {
foremanbuilder.Logger.Fatalf("%s was not created with foreman-builder, foreman-builder will not delete it", containerName)
Expand All @@ -44,8 +47,16 @@ func runDelete(containerName string) {
}
containerInfo, err := foremanbuilder.ContainerInfo(containerName)
if err != nil {
foremanbuilder.Logger.Fatalf("Failed to get container info: %v", err)
os.Exit(1)
if strings.Contains(err.Error(), fmt.Sprintf("machine not found: '%s'", containerName)) {
foremanbuilder.Logger.Debugf("Container does not exist in orbstack anymore just delete the line")
foremanbuilder.DeleteLineInFile(containersPath, containerName)
fmt.Printf("%s has been deleted\n", containerName)
os.Exit(1)
} else {
foremanbuilder.Logger.Fatalf("Failed to get container info: %v", err)
os.Exit(1)
}

}
if containerInfo.State == "running" {
var input string
Expand All @@ -57,11 +68,13 @@ func runDelete(containerName string) {
os.Exit(1)
}
// stop container
exec.Command("orbctl", "stop", containerName)
exec.Command("orbctl", "stop", containerName).Run()

}
exec.Command("orbctl", "delete", containerName, "-f")
fmt.Printf("Deleting...\n")
exec.Command("orbctl", "delete", containerName, "-f").Run()

// delete container in dotfile
foremanbuilder.DeleteLineInFile(containersPath, containerName)
fmt.Printf("%s has been deleted\n", containerName)
}
2 changes: 1 addition & 1 deletion foreman-builder/cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func runList() {
}
dotFolderPath := filepath.Join(home, ".foreman-builder")
containersPath := filepath.Join(dotFolderPath, "containers")
containers, err := foremanbuilder.GetAllLines(containersPath)
containers, err := foremanbuilder.GetAllLines(containersPath, "::")
if err != nil {
fmt.Printf("Error getting all containers %v\n", err)
}
Expand Down
3 changes: 2 additions & 1 deletion foreman-builder/cmd/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func SyncContainers() {
}
dotFolderPath := filepath.Join(home, ".foreman-builder")
containersPath := filepath.Join(dotFolderPath, "containers")
foremanContainers, err := foremanbuilder.GetAllLines(containersPath)
foremanContainers, err := foremanbuilder.GetAllLines(containersPath, "::")
if err != nil {
fmt.Printf("Error getting all containers %v\n", err)
foremanbuilder.Logger.Errorf("Error has occurred getting all containers %v\n", err)
Expand All @@ -43,6 +43,7 @@ func SyncContainers() {
for i := 0; i < len(foremanContainers)-1; i++ {
if !slices.Contains(orbContainers, foremanContainers[i]) {
// mark for deletion
foremanbuilder.Logger.Debugf("During sync... deleting %s\n", foremanContainers[i])
err = foremanbuilder.DeleteLineInFile(containersPath, foremanContainers[i])
if err != nil {
fmt.Printf("Error deleting container from dotfile %v \n", err)
Expand Down
85 changes: 0 additions & 85 deletions foreman-builder/cmd/tui.go

This file was deleted.

52 changes: 48 additions & 4 deletions foreman-builder/dotfolder.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package foremanbuilder

import (
"errors"
"fmt"
"os"
"strings"
)
Expand Down Expand Up @@ -45,7 +46,7 @@ func DeleteLineInFile(path, name string) error {
if strings.TrimSpace(line) == "" {
continue
}
if line != name {
if strings.Split(line, "::")[0] != name {
kept = append(kept, line)
}
}
Expand All @@ -59,12 +60,55 @@ func DeleteLineInFile(path, name string) error {

return os.Rename(tempFile, path)
}

func GetAllLines(path string) ([]string, error) {
func GetAllLines(path, splitBy string) ([]string, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, err
}
return strings.Split(string(data), "\n"), nil

lines := strings.Split(string(data), "\n")

if splitBy == "" {
return lines, nil
}

var splitLines []string
for _, line := range lines {
parts := strings.SplitN(line, splitBy, 2)
splitLines = append(splitLines, parts[0])
}

return splitLines, nil
}

// Can also be used to check if line exists in file, due to return error "not found" if line does not exist
// using containerType == "" will just check for the containerName itself and not care what `-<container-type>`
// example: We want to find a container named container1
func GetLineInFile(path, line, containerType string) (string, error) {
data, err := os.ReadFile(path)
if err != nil {
return "", err
}
var lines []string
for s := range strings.SplitSeq(string(data), "\n") {
lines = append(lines, s)
}
// if containerType == "" we can just ignore container postfix
for _, fileLine := range lines {
if strings.TrimSpace(fileLine) == "" {
continue
}
filePrefix := strings.SplitN(fileLine, "::", 2)[0]
searchPrefix := strings.SplitN(line, "::", 2)[0]
if containerType != "" {
containerMatch := fmt.Sprintf("%s::%s", searchPrefix, containerType)
if containerMatch == fileLine {
return fileLine, nil
}
}
if filePrefix == searchPrefix {
return fileLine, nil
}
}
return "", errors.New("not_found")
}
Loading
Loading