Skip to content

Commit

Permalink
Feature/Docker Compose for a quick database spin-up (#113)
Browse files Browse the repository at this point in the history
Adding docker-compose for db creation
  • Loading branch information
Ujstor authored Nov 25, 2023
1 parent 3bfe912 commit f8218ce
Show file tree
Hide file tree
Showing 21 changed files with 236 additions and 9 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ go-blueprint create
You can also use the provided flags to set up a project without interacting with the UI.

```
go-blueprint create --name my-project --framework gin
go-blueprint create --name my-project --framework gin --driver postgres
```

See `go-blueprint create -h` for all the options and shorthands.
Expand Down
74 changes: 68 additions & 6 deletions cmd/program/program.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/melkeydev/go-blueprint/cmd/flags"
tpl "github.com/melkeydev/go-blueprint/cmd/template"
"github.com/melkeydev/go-blueprint/cmd/template/dbdriver"
"github.com/melkeydev/go-blueprint/cmd/template/docker"
"github.com/melkeydev/go-blueprint/cmd/template/framework"
"github.com/melkeydev/go-blueprint/cmd/utils"
"github.com/spf13/cobra"
Expand All @@ -27,8 +28,10 @@ type Project struct {
AbsolutePath string
ProjectType flags.Framework
DBDriver flags.Database
Docker flags.Database
FrameworkMap map[flags.Framework]Framework
DBDriverMap map[flags.Database]Driver
DockerMap map[flags.Database]Docker
}

// A Framework contains the name and templater for a
Expand All @@ -43,6 +46,11 @@ type Driver struct {
templater DBDriverTemplater
}

type Docker struct {
packageName []string
templater DockerTemplater
}

// A Templater has the methods that help build the files
// in the Project folder, and is specific to a Framework
type Templater interface {
Expand All @@ -51,12 +59,17 @@ type Templater interface {
Routes() []byte
RoutesWithDB() []byte
ServerWithDB() []byte
TestHandler() []byte
TestHandler() []byte
}

type DBDriverTemplater interface {
Service() []byte
Env() []byte
EnvExample() []byte
}

type DockerTemplater interface {
Docker() []byte
}

var (
Expand All @@ -80,7 +93,7 @@ const (
cmdApiPath = "cmd/api"
internalServerPath = "internal/server"
internalDatabasePath = "internal/database"
testHandlerPath = "tests"
testHandlerPath = "tests"
)

// ExitCLI checks if the Project has been exited, and closes
Expand Down Expand Up @@ -153,6 +166,23 @@ func (p *Project) createDBDriverMap() {
}
}

func (p *Project) createDockerMap() {
p.DockerMap = make(map[flags.Database]Docker)

p.DockerMap[flags.MySql] = Docker{
packageName: []string{},
templater: docker.MysqlDockerTemplate{},
}
p.DockerMap[flags.Postgres] = Docker{
packageName: []string{},
templater: docker.PostgresDockerTemplate{},
}
p.DockerMap[flags.Mongo] = Docker{
packageName: []string{},
templater: docker.MongoDockerTemplate{},
}
}

// CreateMainFile creates the project folders and files,
// and writes to them depending on the selected options
func (p *Project) CreateMainFile() error {
Expand Down Expand Up @@ -215,12 +245,37 @@ func (p *Project) CreateMainFile() error {

err = p.CreateFileWithInjection(internalDatabasePath, projectPath, "database.go", "database")
if err != nil {
log.Printf("Error injecting server.go file: %v", err)
log.Printf("Error injecting database.go file: %v", err)
cobra.CheckErr(err)
return err
}
}

// Create correct docker compose for the selected driver
if p.DBDriver != "none" {

err = p.CreateFileWithInjection(root, projectPath, ".env.example", "env-example")
if err != nil {
log.Printf("Error injecting .env.example file: %v", err)
cobra.CheckErr(err)
return err
}

if p.DBDriver != "sqlite" {
p.createDockerMap()
p.Docker = p.DBDriver

err = p.CreateFileWithInjection(root, projectPath, "docker-compose.yml", "db-docker")
if err != nil {
log.Printf("Error injecting docker-compose.yml file: %v", err)
cobra.CheckErr(err)
return err
}
} else {
fmt.Println("\nWe are unable to create docker-compose.yml file for an SQLite database")
}
}

// Install the godotenv package
err = utils.GoGetPackage(projectPath, godotenvPackage)
if err != nil {
Expand Down Expand Up @@ -421,9 +476,15 @@ func (p *Project) CreateFileWithInjection(pathToCreate string, projectPath strin
case "database":
createdTemplate := template.Must(template.New(fileName).Parse(string(p.DBDriverMap[p.DBDriver].templater.Service())))
err = createdTemplate.Execute(createdFile, p)
case "tests":
createdTemplate := template.Must(template.New(fileName).Parse(string(p.FrameworkMap[p.ProjectType].templater.TestHandler())))
err = createdTemplate.Execute(createdFile, p)
case "db-docker":
createdTemplate := template.Must(template.New(fileName).Parse(string(p.DockerMap[p.Docker].templater.Docker())))
err = createdTemplate.Execute(createdFile, p)
case "tests":
createdTemplate := template.Must(template.New(fileName).Parse(string(p.FrameworkMap[p.ProjectType].templater.TestHandler())))
err = createdTemplate.Execute(createdFile, p)
case "env-example":
createdTemplate := template.Must(template.New(fileName).Parse(string(p.DBDriverMap[p.DBDriver].templater.EnvExample())))
err = createdTemplate.Execute(createdFile, p)
case "env":
if p.DBDriver != "none" {

Expand All @@ -433,6 +494,7 @@ func (p *Project) CreateFileWithInjection(pathToCreate string, projectPath strin
}
createdTemplate := template.Must(template.New(fileName).Parse(string(bytes.Join(envBytes, []byte("\n")))))
err = createdTemplate.Execute(createdFile, p)

} else {
createdTemplate := template.Must(template.New(fileName).Parse(string(tpl.GlobalEnvTemplate())))
err = createdTemplate.Execute(createdFile, p)
Expand Down
4 changes: 4 additions & 0 deletions cmd/template/dbdriver/files/env/mongo.example.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
DB_HOST=localhost
DB_PORT=27017
DB_USERNAME=melkey
DB_ROOT_PASSWORD=password1234
3 changes: 2 additions & 1 deletion cmd/template/dbdriver/files/env/mongo.tmpl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
DB_HOST=
DB_PORT=
DB_DATABASE=
DB_USERNAME=
DB_ROOT_PASSWORD=
6 changes: 6 additions & 0 deletions cmd/template/dbdriver/files/env/mysql.example.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=blueprint
DB_USERNAME=melkey
DB_PASSWORD=password1234
DB_ROOT_PASSWORD=password4321
3 changes: 2 additions & 1 deletion cmd/template/dbdriver/files/env/mysql.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ DB_HOST=
DB_PORT=
DB_DATABASE=
DB_USERNAME=
DB_PASSWORD=
DB_PASSWORD=
DB_ROOT_PASSWORD=
5 changes: 5 additions & 0 deletions cmd/template/dbdriver/files/env/postgres.example.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
DB_HOST=localhost
DB_PORT=5432
DB_DATABASE=blueprint
DB_USERNAME=melkey
DB_PASSWORD=password1234
1 change: 1 addition & 0 deletions cmd/template/dbdriver/files/env/sqlite.example.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DB_URL=./test.db
7 changes: 7 additions & 0 deletions cmd/template/dbdriver/mongo.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,17 @@ var mongoServiceTemplate []byte
//go:embed files/env/mongo.tmpl
var mongoEnvTemplate []byte

//go:embed files/env/mongo.example.tmpl
var mongoEnvExampleTemplate []byte

func (m MongoTemplate) Service() []byte {
return mongoServiceTemplate
}

func (m MongoTemplate) Env() []byte {
return mongoEnvTemplate
}

func (m MongoTemplate) EnvExample() []byte {
return mongoEnvExampleTemplate
}
7 changes: 7 additions & 0 deletions cmd/template/dbdriver/mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,17 @@ var mysqlServiceTemplate []byte
//go:embed files/env/mysql.tmpl
var mysqlEnvTemplate []byte

//go:embed files/env/mysql.example.tmpl
var mysqlEnvExampleTemplate []byte

func (m MysqlTemplate) Service() []byte {
return mysqlServiceTemplate
}

func (m MysqlTemplate) Env() []byte {
return mysqlEnvTemplate
}

func (m MysqlTemplate) EnvExample() []byte {
return mysqlEnvExampleTemplate
}
7 changes: 7 additions & 0 deletions cmd/template/dbdriver/postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,17 @@ var postgresServiceTemplate []byte
//go:embed files/env/postgres.tmpl
var postgresEnvTemplate []byte

//go:embed files/env/postgres.example.tmpl
var postgresEnvExampleTemplate []byte

func (m PostgresTemplate) Service() []byte {
return postgresServiceTemplate
}

func (m PostgresTemplate) Env() []byte {
return postgresEnvTemplate
}

func (m PostgresTemplate) EnvExample() []byte {
return postgresEnvExampleTemplate
}
7 changes: 7 additions & 0 deletions cmd/template/dbdriver/sqlite.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,17 @@ var sqliteServiceTemplate []byte
//go:embed files/env/sqlite.tmpl
var sqliteEnvTemplate []byte

//go:embed files/env/sqlite.example.tmpl
var sqliteEnvExampleTemplate []byte

func (m SqliteTemplate) Service() []byte {
return sqliteServiceTemplate
}

func (m SqliteTemplate) Env() []byte {
return sqliteEnvTemplate
}

func (m SqliteTemplate) EnvExample() []byte {
return sqliteEnvExampleTemplate
}
15 changes: 15 additions & 0 deletions cmd/template/docker/files/docker-compose/mongo.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: '3.8'

services:
mongo:
image: mongo:latest
environment:
MONGO_INITDB_ROOT_USERNAME: ${DB_USERNAME}
MONGO_INITDB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
ports:
- "${DB_PORT}:27017"
volumes:
- mongo_volume:/data/db

volumes:
mongo_volume:
17 changes: 17 additions & 0 deletions cmd/template/docker/files/docker-compose/mysql.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: '3.8'

services:
mysql:
image: mysql:latest
environment:
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_USER: ${DB_USERNAME}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
ports:
- "${DB_PORT}:3306"
volumes:
- mysql_volume:/var/lib/mysql

volumes:
mysql_volume:
16 changes: 16 additions & 0 deletions cmd/template/docker/files/docker-compose/postgres.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
version: '3.8'

services:
psql:
image: postgres:latest
environment:
POSTGRES_DB: ${DB_DATABASE}
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_PASSWORD: ${DB_PASSWORD}
ports:
- "${DB_PORT}:5432"
volumes:
- psql_volume:/var/lib/postgresql/data

volumes:
psql_volume:
14 changes: 14 additions & 0 deletions cmd/template/docker/mongo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package docker

import (
_ "embed"
)

type MongoDockerTemplate struct{}

//go:embed files/docker-compose/mongo.tmpl
var mongoDockerTemplate []byte

func (m MongoDockerTemplate) Docker() []byte {
return mongoDockerTemplate
}
14 changes: 14 additions & 0 deletions cmd/template/docker/mysql.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package docker

import (
_ "embed"
)

type MysqlDockerTemplate struct{}

//go:embed files/docker-compose/mysql.tmpl
var mysqlDockerTemplate []byte

func (m MysqlDockerTemplate) Docker() []byte {
return mysqlDockerTemplate
}
14 changes: 14 additions & 0 deletions cmd/template/docker/postgres.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package docker

import (
_ "embed"
)

type PostgresDockerTemplate struct{}

//go:embed files/docker-compose/postgres.tmpl
var postgresDockerTemplate []byte

func (m PostgresDockerTemplate) Docker() []byte {
return postgresDockerTemplate
}
10 changes: 10 additions & 0 deletions cmd/template/framework/files/README.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ run the application
make run
```

Create DB container
```bash
make docker-run
```

Shutdown DB container
```bash
make docker-down
```

live reload the application
```bash
make watch
Expand Down
Loading

0 comments on commit f8218ce

Please sign in to comment.