diff --git a/README.md b/README.md index 4b890954..1664eee1 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/cmd/program/program.go b/cmd/program/program.go index 48a01106..9835e3d0 100644 --- a/cmd/program/program.go +++ b/cmd/program/program.go @@ -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" @@ -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 @@ -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 { @@ -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 ( @@ -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 @@ -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 { @@ -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 { @@ -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" { @@ -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) diff --git a/cmd/template/dbdriver/files/env/mongo.example.tmpl b/cmd/template/dbdriver/files/env/mongo.example.tmpl new file mode 100644 index 00000000..8f98d964 --- /dev/null +++ b/cmd/template/dbdriver/files/env/mongo.example.tmpl @@ -0,0 +1,4 @@ +DB_HOST=localhost +DB_PORT=27017 +DB_USERNAME=melkey +DB_ROOT_PASSWORD=password1234 \ No newline at end of file diff --git a/cmd/template/dbdriver/files/env/mongo.tmpl b/cmd/template/dbdriver/files/env/mongo.tmpl index 312eb609..85606f8e 100644 --- a/cmd/template/dbdriver/files/env/mongo.tmpl +++ b/cmd/template/dbdriver/files/env/mongo.tmpl @@ -1,3 +1,4 @@ DB_HOST= DB_PORT= -DB_DATABASE= \ No newline at end of file +DB_USERNAME= +DB_ROOT_PASSWORD= \ No newline at end of file diff --git a/cmd/template/dbdriver/files/env/mysql.example.tmpl b/cmd/template/dbdriver/files/env/mysql.example.tmpl new file mode 100644 index 00000000..4f1c1f91 --- /dev/null +++ b/cmd/template/dbdriver/files/env/mysql.example.tmpl @@ -0,0 +1,6 @@ +DB_HOST=localhost +DB_PORT=3306 +DB_DATABASE=blueprint +DB_USERNAME=melkey +DB_PASSWORD=password1234 +DB_ROOT_PASSWORD=password4321 \ No newline at end of file diff --git a/cmd/template/dbdriver/files/env/mysql.tmpl b/cmd/template/dbdriver/files/env/mysql.tmpl index de778fd3..03d0169a 100644 --- a/cmd/template/dbdriver/files/env/mysql.tmpl +++ b/cmd/template/dbdriver/files/env/mysql.tmpl @@ -2,4 +2,5 @@ DB_HOST= DB_PORT= DB_DATABASE= DB_USERNAME= -DB_PASSWORD= \ No newline at end of file +DB_PASSWORD= +DB_ROOT_PASSWORD= \ No newline at end of file diff --git a/cmd/template/dbdriver/files/env/postgres.example.tmpl b/cmd/template/dbdriver/files/env/postgres.example.tmpl new file mode 100644 index 00000000..77a0bede --- /dev/null +++ b/cmd/template/dbdriver/files/env/postgres.example.tmpl @@ -0,0 +1,5 @@ +DB_HOST=localhost +DB_PORT=5432 +DB_DATABASE=blueprint +DB_USERNAME=melkey +DB_PASSWORD=password1234 \ No newline at end of file diff --git a/cmd/template/dbdriver/files/env/sqlite.example.tmpl b/cmd/template/dbdriver/files/env/sqlite.example.tmpl new file mode 100644 index 00000000..39612ef1 --- /dev/null +++ b/cmd/template/dbdriver/files/env/sqlite.example.tmpl @@ -0,0 +1 @@ +DB_URL=./test.db diff --git a/cmd/template/dbdriver/mongo.go b/cmd/template/dbdriver/mongo.go index e8156a41..137ffe0c 100644 --- a/cmd/template/dbdriver/mongo.go +++ b/cmd/template/dbdriver/mongo.go @@ -12,6 +12,9 @@ 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 } @@ -19,3 +22,7 @@ func (m MongoTemplate) Service() []byte { func (m MongoTemplate) Env() []byte { return mongoEnvTemplate } + +func (m MongoTemplate) EnvExample() []byte { + return mongoEnvExampleTemplate +} \ No newline at end of file diff --git a/cmd/template/dbdriver/mysql.go b/cmd/template/dbdriver/mysql.go index 42f9de7e..5c37a277 100644 --- a/cmd/template/dbdriver/mysql.go +++ b/cmd/template/dbdriver/mysql.go @@ -12,6 +12,9 @@ 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 } @@ -19,3 +22,7 @@ func (m MysqlTemplate) Service() []byte { func (m MysqlTemplate) Env() []byte { return mysqlEnvTemplate } + +func (m MysqlTemplate) EnvExample() []byte { + return mysqlEnvExampleTemplate +} \ No newline at end of file diff --git a/cmd/template/dbdriver/postgres.go b/cmd/template/dbdriver/postgres.go index 875836b0..c072c6d1 100644 --- a/cmd/template/dbdriver/postgres.go +++ b/cmd/template/dbdriver/postgres.go @@ -12,6 +12,9 @@ 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 } @@ -19,3 +22,7 @@ func (m PostgresTemplate) Service() []byte { func (m PostgresTemplate) Env() []byte { return postgresEnvTemplate } + +func (m PostgresTemplate) EnvExample() []byte { + return postgresEnvExampleTemplate +} \ No newline at end of file diff --git a/cmd/template/dbdriver/sqlite.go b/cmd/template/dbdriver/sqlite.go index 55a5dccb..ac1af459 100644 --- a/cmd/template/dbdriver/sqlite.go +++ b/cmd/template/dbdriver/sqlite.go @@ -12,6 +12,9 @@ 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 } @@ -19,3 +22,7 @@ func (m SqliteTemplate) Service() []byte { func (m SqliteTemplate) Env() []byte { return sqliteEnvTemplate } + +func (m SqliteTemplate) EnvExample() []byte { + return sqliteEnvExampleTemplate +} \ No newline at end of file diff --git a/cmd/template/docker/files/docker-compose/mongo.tmpl b/cmd/template/docker/files/docker-compose/mongo.tmpl new file mode 100644 index 00000000..e7c6cdb1 --- /dev/null +++ b/cmd/template/docker/files/docker-compose/mongo.tmpl @@ -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: \ No newline at end of file diff --git a/cmd/template/docker/files/docker-compose/mysql.tmpl b/cmd/template/docker/files/docker-compose/mysql.tmpl new file mode 100644 index 00000000..8494a227 --- /dev/null +++ b/cmd/template/docker/files/docker-compose/mysql.tmpl @@ -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: \ No newline at end of file diff --git a/cmd/template/docker/files/docker-compose/postgres.tmpl b/cmd/template/docker/files/docker-compose/postgres.tmpl new file mode 100644 index 00000000..0a98c007 --- /dev/null +++ b/cmd/template/docker/files/docker-compose/postgres.tmpl @@ -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: \ No newline at end of file diff --git a/cmd/template/docker/mongo.go b/cmd/template/docker/mongo.go new file mode 100644 index 00000000..7b061716 --- /dev/null +++ b/cmd/template/docker/mongo.go @@ -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 +} \ No newline at end of file diff --git a/cmd/template/docker/mysql.go b/cmd/template/docker/mysql.go new file mode 100644 index 00000000..1239c3d0 --- /dev/null +++ b/cmd/template/docker/mysql.go @@ -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 +} \ No newline at end of file diff --git a/cmd/template/docker/postgres.go b/cmd/template/docker/postgres.go new file mode 100644 index 00000000..edb47dbd --- /dev/null +++ b/cmd/template/docker/postgres.go @@ -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 +} \ No newline at end of file diff --git a/cmd/template/framework/files/README.md.tmpl b/cmd/template/framework/files/README.md.tmpl index 57ac9b81..bd551bc2 100644 --- a/cmd/template/framework/files/README.md.tmpl +++ b/cmd/template/framework/files/README.md.tmpl @@ -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 diff --git a/cmd/template/framework/files/makefile.tmpl b/cmd/template/framework/files/makefile.tmpl index ba4dca86..c45f22b1 100644 --- a/cmd/template/framework/files/makefile.tmpl +++ b/cmd/template/framework/files/makefile.tmpl @@ -11,6 +11,24 @@ build: run: @go run cmd/api/main.go +# Create DB container +docker-run: + @if docker compose up 2>/dev/null; then \ + : ; \ + else \ + echo "Falling back to Docker Compose V1"; \ + docker-compose up; \ + fi + +# Shutdown DB container +docker-down: + @if docker compose down 2>/dev/null; then \ + : ; \ + else \ + echo "Falling back to Docker Compose V1"; \ + docker-compose down; \ + fi + # Test the application test: @echo "Testing..." diff --git a/contributors.yml b/contributors.yml index 15270ecf..340b992f 100644 --- a/contributors.yml +++ b/contributors.yml @@ -18,3 +18,4 @@ - muandane - SputNikPlop - Yoquec +- Ujstor