Skip to content
Open
Show file tree
Hide file tree
Changes from 11 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
8 changes: 5 additions & 3 deletions assets/local-beach/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ services:
environment:
- DEFAULT_HOST=hello.localbeach.net
database:
image: mariadb:10.11
image: mysql:8.0
container_name: local_beach_database
networks:
- local_beach
volumes:
- {{databasePath}}:/var/lib/mysql
- {{mysqlDatabasePath}}:/var/lib/mysql
healthcheck:
test: "/usr/bin/mysql --user=root --password=password --execute \"SHOW DATABASES;\""
interval: 3s
Expand All @@ -32,4 +32,6 @@ services:
- MYSQL_ROOT_PASSWORD=password
ports:
- 3307:3306
command: 'mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci'
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
42 changes: 42 additions & 0 deletions assets/local-beach/mariadb-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
networks:
local_beach:
external: true

services:
database:
image: mysql:8.0
container_name: local_beach_database
networks:
- local_beach
volumes:
- {{mysqlDatabasePath}}:/var/lib/mysql
healthcheck:
test: "/usr/bin/mysql --user=root --password=password --execute \"SHOW DATABASES;\""
interval: 3s
timeout: 1s
retries: 10
environment:
- MYSQL_ROOT_PASSWORD=password
ports:
- 3307:3306
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci

mariadb:
image: mariadb:10.11
container_name: local_beach_mariadb
networks:
- local_beach
volumes:
- {{mariadbDatabasePath}}:/var/lib/mysql
healthcheck:
test: "/usr/bin/mysql --user=root --password=password --execute \"SHOW DATABASES;\""
interval: 3s
timeout: 1s
retries: 10
environment:
- MYSQL_ROOT_PASSWORD=password
ports:
- 3306:3306
command: 'mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci'
79 changes: 1 addition & 78 deletions cmd/beach/cmd/down.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,6 @@
package cmd

import (
"errors"
"os"
"path/filepath"
"strings"

"github.com/flownative/localbeach/pkg/path"

"github.com/flownative/localbeach/pkg/beachsandbox"
"github.com/flownative/localbeach/pkg/exec"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
Expand All @@ -42,75 +33,7 @@ func init() {
}

func handleDownRun(cmd *cobra.Command, args []string) {
instanceRoots, err := findInstanceRoots()
if err != nil {
if err := bringBeachDown(); err != nil {
log.Fatal(err)
return
}
for _, instanceRoot := range instanceRoots {
log.Info("Stopping instance in " + instanceRoot + "...")
sandbox, err := beachsandbox.GetSandbox(instanceRoot)
if err != nil && !errors.Is(err, beachsandbox.ErrNoFlowFound) {
log.Fatal(err)
return
}
commandArgs := []string{"compose", "-f", sandbox.DockerComposeFilePath, "rm", "--force", "--stop", "-v"}
output, err := exec.RunCommand("docker", commandArgs)
if err != nil {
log.Fatal(output)
return
}
}

log.Info("Stopping reverse proxy and database server ...")
commandArgs := []string{"compose", "-f", filepath.Join(path.Base, "docker-compose.yml"), "rm", "--force", "--stop", "-v"}
output, err := exec.RunCommand("docker", commandArgs)
if err != nil {
log.Fatal(output)
return
}

return
}

func findInstanceRoots() ([]string, error) {
var configurationFiles []string

output, err := exec.RunCommand("docker", []string{"ps", "-q", "--filter", "network=local_beach"})
if err != nil {
return nil, errors.New(output)
}
for _, line := range strings.Split(output, "\n") {
containerID := strings.TrimSpace(line)
if len(containerID) > 0 {
output, err := exec.RunCommand("docker", []string{"inspect", "-f", "{{index .Config.Labels \"com.docker.compose.project.config_files\"}}", containerID})
if err != nil {
return nil, errors.New(output)
}
projectDirectory := filepath.Dir(strings.TrimSpace(output))
if containsLocalBeachInstance(projectDirectory) {
configurationFiles = append(configurationFiles, projectDirectory)
}
}
}

return removeDuplicates(configurationFiles), nil
}

func containsLocalBeachInstance(path string) bool {
path = filepath.Join(path, ".localbeach.docker-compose.yaml")
_, err := os.Stat(path)
return !errors.Is(err, os.ErrNotExist)
}

func removeDuplicates(strSlice []string) []string {
allKeys := make(map[string]bool)
var list []string
for _, item := range strSlice {
if _, value := allKeys[item]; !value {
allKeys[item] = true
list = append(list, item)
}
}
return list
}
131 changes: 115 additions & 16 deletions cmd/beach/cmd/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,16 @@ import (
"encoding/base64"
"errors"
"fmt"
"github.com/flownative/localbeach/pkg/path"
"io"
"net/http"
"os"
"path/filepath"
"strings"
"time"

"github.com/flownative/localbeach/pkg/beachsandbox"
"github.com/flownative/localbeach/pkg/exec"
"github.com/flownative/localbeach/pkg/path"
log "github.com/sirupsen/logrus"

asset "github.com/flownative/localbeach/assets"
Expand Down Expand Up @@ -144,6 +145,49 @@ func retrieveCloudStorageCredentials(instanceIdentifier string, projectNamespace
return nil, bucketName, privateKey
}

func writeComposeFile(assetPath, outputFileName string, replacements map[string]string) error {
composeFileContent := readFileFromAssets(assetPath)

// Apply all replacements
for placeholder, value := range replacements {
composeFileContent = strings.ReplaceAll(composeFileContent, placeholder, value)
}

outputPath := filepath.Join(path.Base, outputFileName)
destination, err := os.Create(outputPath)
if err != nil {
return fmt.Errorf("failed creating %s: %w", outputFileName, err)
}
defer destination.Close()

_, err = destination.WriteString(composeFileContent)
if err != nil {
return fmt.Errorf("failed writing to %s: %w", outputFileName, err)
}

return nil
}

func writeLocalBeachComposeFile() {
replacements := map[string]string{
"{{mysqlDatabasePath}}": path.MySQLDatabase,
"{{certificatesPath}}": path.Certificates,
}
if err := writeComposeFile("local-beach/docker-compose.yml", "docker-compose.yml", replacements); err != nil {
log.Error(err)
}
}

func writeMariaDBComposeFile() {
replacements := map[string]string{
"{{mysqlDatabasePath}}": path.MySQLDatabase,
"{{mariadbDatabasePath}}": path.MariaDBDatabase,
}
if err := writeComposeFile("local-beach/mariadb-compose.yml", "mariadb-compose.yml", replacements); err != nil {
log.Error(err)
}
}

func startLocalBeach() error {
_, err := os.Stat(path.Base)
if os.IsNotExist(err) {
Expand All @@ -164,21 +208,7 @@ func startLocalBeach() error {
}

if len(nginxStatusOutput) == 0 || len(databaseStatusOutput) == 0 {
composeFileContent := readFileFromAssets("local-beach/docker-compose.yml")
composeFileContent = strings.ReplaceAll(composeFileContent, "{{databasePath}}", path.Database)
composeFileContent = strings.ReplaceAll(composeFileContent, "{{certificatesPath}}", path.Certificates)

destination, err := os.Create(filepath.Join(path.Base, "docker-compose.yml"))
if err != nil {
log.Error("failed creating docker-compose.yml: ", err)
} else {
_, err = destination.WriteString(composeFileContent)
if err != nil {
log.Error(err)
}

}
_ = destination.Close()
writeLocalBeachComposeFile()

log.Info("Starting reverse proxy and database server ...")
commandArgs := []string{"compose", "-f", filepath.Join(path.Base, "docker-compose.yml"), "up", "--remove-orphans", "-d"}
Expand Down Expand Up @@ -206,3 +236,72 @@ func startLocalBeach() error {
}
return nil
}

func bringBeachDown() error {
instanceRoots, err := findInstanceRoots()
if err != nil {
return fmt.Errorf("failed to find instance roots: %w", err)
}
for _, instanceRoot := range instanceRoots {
log.Info("Stopping instance in " + instanceRoot + "...")
sandbox, err := beachsandbox.GetSandbox(instanceRoot)
if err != nil && !errors.Is(err, beachsandbox.ErrNoFlowFound) {
return fmt.Errorf("failed to get sandbox for %s: %w", instanceRoot, err)
}
commandArgs := []string{"compose", "-f", sandbox.DockerComposeFilePath, "rm", "--force", "--stop", "-v"}
output, err := exec.RunCommand("docker", commandArgs)
if err != nil {
return fmt.Errorf("failed to stop instance in %s: %s", instanceRoot, output)
}
}

log.Info("Stopping reverse proxy and database server ...")
commandArgs := []string{"compose", "-f", filepath.Join(path.Base, "docker-compose.yml"), "rm", "--force", "--stop", "-v"}
output, err := exec.RunCommand("docker", commandArgs)
if err != nil {
return fmt.Errorf("failed to stop reverse proxy and database: %s", output)
}
return nil
}

func findInstanceRoots() ([]string, error) {
var configurationFiles []string

output, err := exec.RunCommand("docker", []string{"ps", "-q", "--filter", "network=local_beach"})
if err != nil {
return nil, errors.New(output)
}
for _, line := range strings.Split(output, "\n") {
containerID := strings.TrimSpace(line)
if len(containerID) > 0 {
output, err := exec.RunCommand("docker", []string{"inspect", "-f", "{{index .Config.Labels \"com.docker.compose.project.config_files\"}}", containerID})
if err != nil {
return nil, errors.New(output)
}
projectDirectory := filepath.Dir(strings.TrimSpace(output))
if containsLocalBeachInstance(projectDirectory) {
configurationFiles = append(configurationFiles, projectDirectory)
}
}
}

return removeDuplicates(configurationFiles), nil
}

func containsLocalBeachInstance(path string) bool {
path = filepath.Join(path, ".localbeach.docker-compose.yaml")
_, err := os.Stat(path)
return !errors.Is(err, os.ErrNotExist)
}

func removeDuplicates(strSlice []string) []string {
allKeys := make(map[string]bool)
var list []string
for _, item := range strSlice {
if _, value := allKeys[item]; !value {
allKeys[item] = true
list = append(list, item)
}
}
return list
}
3 changes: 2 additions & 1 deletion cmd/beach/cmd/pause.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
package cmd

import (
"path/filepath"

"github.com/flownative/localbeach/pkg/exec"
"github.com/flownative/localbeach/pkg/path"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"path/filepath"
)

// pauseCmd represents the pause command
Expand Down
Loading