Skip to content

Commit 409ee37

Browse files
committed
- configuration and database implementation
1 parent b002b4e commit 409ee37

11 files changed

Lines changed: 696 additions & 82 deletions

File tree

riotpot/configuration/conf_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package configuration
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"os"
7+
"testing"
8+
)
9+
10+
var (
11+
settings = Settings{}
12+
path = "."
13+
fLoad = "configuration"
14+
fSave = "temp"
15+
err error
16+
)
17+
18+
// Test loading and saving configuration from a file to another
19+
func TestLoadAndSaveConf(t *testing.T) {
20+
21+
// load the configuration
22+
err = settings.Load(path, fLoad)
23+
if err != nil {
24+
t.Error(err)
25+
}
26+
27+
// pretty print marshalling to json
28+
out, err := json.MarshalIndent(settings, "", " ")
29+
if err != nil {
30+
t.Error(err)
31+
}
32+
33+
t.Logf("%s\n", string(out))
34+
35+
// save the configuration
36+
err = settings.Save(path, fSave)
37+
if err != nil {
38+
t.Error(err)
39+
}
40+
41+
// read the file just saved and prints it
42+
fp := fmt.Sprintf("%s/%s.yml", path, fSave)
43+
data, err := os.ReadFile(fp)
44+
if err != nil {
45+
t.Error(err)
46+
}
47+
48+
t.Log(string(data))
49+
}

riotpot/configuration/configuration.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,33 +27,37 @@ type Settings struct {
2727
}
2828

2929
// Takes configuration data as string and updates the state of a given configuration based on it.
30-
func (conf *Settings) Load(path string, filename string) {
30+
func (conf *Settings) Load(path string, filename string) error {
3131
// full path of the file.
32-
var filepath = fmt.Sprintf("%s/%s.yaml", path, filename)
32+
var filepath = fmt.Sprintf("%s/%s.yml", path, filename)
3333

3434
// load the data into the memory
3535
data, err := os.ReadFile(filepath)
3636
errors.Raise(err)
3737

3838
// unmarshal the data into the configuration settings.
39-
err = yaml.Unmarshal([]byte(data), &conf)
39+
err = yaml.Unmarshal(data, &conf)
4040
errors.Raise(err)
41+
42+
return err
4143
}
4244

4345
// Stores the configuration into the given path in `.yml` format.
44-
func (conf Settings) Save(path string, filename string) {
46+
func (conf Settings) Save(path string, filename string) error {
4547
// marshal the content of the configuration into a `.yaml` document
4648
d, err := yaml.Marshal(&conf)
4749
errors.Raise(err)
4850

4951
// full path of the file.
50-
var filepath = fmt.Sprintf("%s/%s.yaml", path, filename)
52+
var filepath = fmt.Sprintf("%s/%s.yml", path, filename)
5153

5254
// Save to file.
5355
// Mode 640: https://chmodcommand.com/chmod-640/
5456
// Note: this truncates the file if it already exists !!!
5557
err = os.WriteFile(filepath, d, 0640)
5658
errors.Raise(err)
59+
60+
return err
5761
}
5862

5963
// This method overwrites the settings with the values from the environment
@@ -87,14 +91,14 @@ func (conf Settings) ResolveEnv() {
8791
// Provides common identification attributes for each configuration.
8892
// This structure must be private for each configuration object.
8993
type ConfigIdentity struct {
90-
id string
91-
name string
94+
ID string
95+
Name string `yaml:"name"`
9296
}
9397

9498
// RiotPot configuration structure. It includes all the attributes related to the riotpot framework.
9599
// Moreover, it defines the emulators that must be loaded, and watches over them during runtime.
96100
type ConfigRiotpot struct {
97-
identity ConfigIdentity
101+
Identity ConfigIdentity
98102

99103
/* Riotpot configuration attributes: */
100104
// Defines if the emulators must be loaded directly from the file system.
@@ -134,7 +138,7 @@ func (conf *ConfigRiotpot) Validated() []string {
134138

135139
// Database configuration structure. It gives an interface to load and access specific databases.
136140
type ConfigDatabase struct {
137-
identity ConfigIdentity
141+
Identity ConfigIdentity
138142

139143
/* Database configuration */
140144
// engine used in the db e.g. sql, postgres, sqlite

riotpot/configuration/configuration.yml

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1+
---
12
version: 1
23
type: template
34
# RiotPot configuration file.
45
# This file can be used as a template for further implementations and as a record of
56
# documentation for internal structure when in doubt on usage.
6-
---
77

88
# 50 characters minimum long RANDOM string used to generate cryptographic signatures.
99
secret:
@@ -14,6 +14,7 @@ riotpot:
1414
# If this boolean is set to a falsy value then `start` must be filled with the
1515
# list of emulators desired to be loaded and run at start.
1616
autodiscover: false
17+
1718
# `start` contains a list of emulator services desired to be started
1819
# on-start. For all the services, set `autodiscover` to `true`.
1920
start:
@@ -36,19 +37,23 @@ riotpot:
3637
# connection information. As the name indicates, `default` will be the default
3738
# database used to store logs, binary entries, etc.
3839
databases:
39-
default:
40-
# RiotPot supports: sql, sqlite, and postgres.
41-
engine: sqlite
40+
-
41+
identity:
42+
# Name of the targeted database
43+
name: default
44+
# RiotPot only supports postgres currently.
45+
engine: postgres
4246
# IP or container name in the same network.
43-
host:
47+
host: localhost
4448
# Connection port to the database host.
45-
port:
49+
port: 5432
4650
# User and password to access the database.
4751
# NOTE: Do not hard-code the values in this file. Please do make
4852
# use of `.env` file for this purpose in production.
49-
user:
53+
username: superuser
5054
password:
5155

56+
---
5257
# USER +---------------------------+ USER
5358
# Declare here configuration information regarding the user.
5459
# The user information is used to create a profile for the current
@@ -66,4 +71,5 @@ user:
6671
# plaintext value, refer instead to `.env` file.
6772
password:
6873
# USER +---------------------------+ USER
74+
---
6975

riotpot/database/database.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package database
2+
3+
import (
4+
"fmt"
5+
"riotpot/configuration"
6+
"riotpot/utils/errors"
7+
8+
"gorm.io/driver/postgres"
9+
"gorm.io/gorm"
10+
)
11+
12+
// Struct that defines the database connection.
13+
// the database connection uses a pool so multiple
14+
// services can push information to the database simultaneously
15+
// through riotpot.
16+
type Database struct {
17+
// Database configuration
18+
config configuration.ConfigDatabase
19+
20+
// Pointer to the db connection
21+
conn *gorm.DB
22+
}
23+
24+
// Method to create a connection pool to the database
25+
func (db *Database) connect() (*gorm.DB, error) {
26+
// build the connection url as a string
27+
dsn := fmt.Sprintf(
28+
"host=%s user=%s password=%s dbname=%s port=%s sslmode=disable",
29+
db.config.Host,
30+
db.config.Username,
31+
db.config.Password,
32+
db.config.Identity.Name,
33+
db.config.Port,
34+
)
35+
36+
// create the pool connection to the database using its configuration.
37+
// It uses pgx as a default driver.
38+
conn, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
39+
errors.Raise(err)
40+
41+
db.conn = conn
42+
43+
// returns the connection pool as a pointer
44+
return db.conn, err
45+
}
46+
47+
// Get the connection to the database or create a new one.
48+
func (db *Database) Connection() *gorm.DB {
49+
// check if there is any connection at all
50+
if db.conn != nil {
51+
return db.conn
52+
} else {
53+
conn, err := db.connect()
54+
errors.Raise(err)
55+
return conn
56+
}
57+
}

riotpot/database/db_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package database
2+
3+
import (
4+
"fmt"
5+
"riotpot/configuration"
6+
"testing"
7+
8+
"gorm.io/gorm"
9+
)
10+
11+
type UserTest struct {
12+
gorm.Model
13+
Name string
14+
}
15+
16+
// Runs a simple test to check the health of a database and the configuration.
17+
// Keep in mind this function requires the role `superuser` and the `superuser` db
18+
// to previously exists!
19+
// Example:
20+
// $ # create the user as a superuser and the db
21+
// $ createuser superuser -s
22+
// $ createdb superuser
23+
func TestDatabase(t *testing.T) {
24+
25+
var (
26+
// Load an identity for the database
27+
id = configuration.ConfigIdentity{
28+
Name: "test_db",
29+
}
30+
31+
// Load a configuration for the database
32+
config = configuration.ConfigDatabase{
33+
Username: "superuser",
34+
Password: "",
35+
Host: "127.0.0.1",
36+
Identity: id,
37+
Port: "5432",
38+
}
39+
40+
// Load a database object
41+
db = Database{
42+
config: config,
43+
}
44+
45+
// Load a random user
46+
user = UserTest{
47+
Name: "Test",
48+
}
49+
)
50+
51+
// Connect to the db
52+
conn := db.Connection()
53+
54+
// create and move to the db
55+
conn = conn.Exec(fmt.Sprintf("CREATE DATABASE %s", db.config.Identity.Name))
56+
57+
// migrate the model
58+
conn.AutoMigrate(&UserTest{})
59+
60+
// Insert the user in the database
61+
result := conn.Create(&user)
62+
if result.Error != nil {
63+
t.Error(result.Error)
64+
}
65+
66+
// Log some of the results...
67+
t.Logf("User ID: %v", user.ID)
68+
t.Logf("User Name: %v", user.Name)
69+
}

riotpot/echod/echod.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"bufio"
55
"fmt"
6+
"log"
67
"net"
78
"riotpot/services"
89
"riotpot/utils/errors"
@@ -102,7 +103,7 @@ func (e *Echo) handleConn(conn net.Conn) {
102103
func (e *Echo) save(address net.Addr, msg []byte) {
103104
// TODO: add logic here to store the connections made
104105
// to the server
105-
fmt.Printf("Bip Bop... \nSaving connection:\n> address: %v\n> msg: %v", address, msg)
106+
fmt.Printf("Bip Bop... \nSaving connection:\n> address: %v\n> msg: %s", address, msg)
106107
}
107108

108109
func (e *Echo) Stop() error {
@@ -122,9 +123,9 @@ func (e *Echo) Status() error {
122123
return err
123124
}
124125

125-
func (e *Echo) Logger(ch chan<- error) (services.Logger, error) {
126+
func (e *Echo) Logger(ch chan<- error) (log.Logger, error) {
126127
var (
127-
logger services.Logger
128+
logger log.Logger
128129
err error
129130
)
130131
return logger, err

riotpot/go.mod

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ go 1.16
55
require (
66
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
77
github.com/gliderlabs/ssh v0.3.2
8+
github.com/jackc/pgx/v4 v4.11.0 // indirect
89
github.com/kr/pty v1.1.8
9-
github.com/labstack/gommon v0.3.0
10-
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 // indirect
11-
golang.org/x/sys v0.0.0-20210304152209-afaa3650a925 // indirect
12-
gopkg.in/yaml.v2 v2.4.0
10+
github.com/stretchr/testify v1.7.0 // indirect
11+
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 // indirect
1312
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
13+
gorm.io/driver/postgres v1.0.8
14+
gorm.io/gorm v1.21.6
1415
)

0 commit comments

Comments
 (0)