Skip to content

Commit 135697a

Browse files
committed
Updated
1 parent 9472ba4 commit 135697a

File tree

3 files changed

+123
-24
lines changed

3 files changed

+123
-24
lines changed

README.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,26 @@ features and functionality as needed. More documentation soon on how to do that.
1616

1717
## Running
1818

19-
You can run the server in a docker container or build it from source. To run the latest
20-
released version as a docker container:
19+
The binary includes both the *server*-side application and the *client*-side
20+
command-line tools. Both can be run as docker containers.
21+
22+
To run the latest released version as a docker container:
2123

2224
```bash
2325
docker run ghcr.io/mutablelogic/go-server:latest
2426
```
2527

26-
This will print out the help message.
28+
This will print out the help message and provide insight into running both the server application
29+
and interacting with the server through commands. To run the server, you'll need a PostgreSQL
30+
database, and you can set the environment variables `PG_HOST`, `PG_DATABASE`, `PG_USER` and `PG_PASS`.
31+
32+
### Bootstrapping the database server and roles
33+
34+
More information about setting up the databses TODO
35+
36+
### Creating a new database
37+
38+
Information about setting up a new database
2739

2840
## Building
2941

cmd/server/service.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,14 @@ func (cmd *ServiceRunCommand) Run(app server.Cmd) error {
128128
auth := config.(*auth.Config)
129129

130130
// Set the router
131-
if router, ok := ref.Provider(ctx).Task(ctx, "httprouter").(server.HTTPRouter); !ok || router == nil {
131+
if router, ok := ref.Provider(ctx).Task(ctx, "httprouter.main").(server.HTTPRouter); !ok || router == nil {
132132
return httpresponse.ErrInternalError.With("Invalid router")
133133
} else {
134134
auth.Router = router
135135
}
136136

137137
// Set the connection pool
138-
if pool, ok := ref.Provider(ctx).Task(ctx, "pgpool").(server.PG); !ok || pool == nil {
138+
if pool, ok := ref.Provider(ctx).Task(ctx, "pgpool.main").(server.PG); !ok || pool == nil {
139139
return httpresponse.ErrInternalError.With("Invalid connection pool")
140140
} else {
141141
auth.Pool = pool
@@ -148,14 +148,14 @@ func (cmd *ServiceRunCommand) Run(app server.Cmd) error {
148148
pgqueue := config.(*pgqueue.Config)
149149

150150
// Set the router
151-
if router, ok := ref.Provider(ctx).Task(ctx, "httprouter").(server.HTTPRouter); !ok || router == nil {
151+
if router, ok := ref.Provider(ctx).Task(ctx, "httprouter.main").(server.HTTPRouter); !ok || router == nil {
152152
return httpresponse.ErrInternalError.With("Invalid router")
153153
} else {
154154
pgqueue.Router = router
155155
}
156156

157157
// Set the connection pool
158-
if pool, ok := ref.Provider(ctx).Task(ctx, "pgpool").(server.PG); !ok || pool == nil {
158+
if pool, ok := ref.Provider(ctx).Task(ctx, "pgpool.main").(server.PG); !ok || pool == nil {
159159
return httpresponse.ErrInternalError.With("Invalid connection pool")
160160
} else {
161161
pgqueue.Pool = pool
@@ -167,21 +167,21 @@ func (cmd *ServiceRunCommand) Run(app server.Cmd) error {
167167
certmanager := config.(*cert.Config)
168168

169169
// Set the router
170-
if router, ok := ref.Provider(ctx).Task(ctx, "httprouter").(server.HTTPRouter); !ok || router == nil {
170+
if router, ok := ref.Provider(ctx).Task(ctx, "httprouter.main").(server.HTTPRouter); !ok || router == nil {
171171
return httpresponse.ErrInternalError.With("Invalid router")
172172
} else {
173173
certmanager.Router = router
174174
}
175175

176176
// Set the connection pool
177-
if pool, ok := ref.Provider(ctx).Task(ctx, "pgpool").(server.PG); !ok || pool == nil {
177+
if pool, ok := ref.Provider(ctx).Task(ctx, "pgpool.main").(server.PG); !ok || pool == nil {
178178
return httpresponse.ErrInternalError.With("Invalid connection pool")
179179
} else {
180180
certmanager.Pool = pool
181181
}
182182

183183
// Set the queue
184-
if queue, ok := ref.Provider(ctx).Task(ctx, "pgqueue").(server.PGQueue); !ok || queue == nil {
184+
if queue, ok := ref.Provider(ctx).Task(ctx, "pgqueue.main").(server.PGQueue); !ok || queue == nil {
185185
return httpresponse.ErrInternalError.With("Invalid task queue")
186186
} else {
187187
certmanager.Queue = queue

pkg/provider/meta/meta.go

Lines changed: 101 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@ import (
55
"fmt"
66
"io"
77
"net/url"
8+
"os"
89
"reflect"
9-
"strings"
10+
"strconv"
1011
"time"
1112

1213
// Packages
13-
"github.com/mutablelogic/go-server"
14+
server "github.com/mutablelogic/go-server"
1415
httpresponse "github.com/mutablelogic/go-server/pkg/httpresponse"
1516
ast "github.com/mutablelogic/go-server/pkg/parser/ast"
17+
types "github.com/mutablelogic/go-server/pkg/types"
1618
)
1719

1820
////////////////////////////////////////////////////////////////////////////////
@@ -21,7 +23,9 @@ import (
2123
type Meta struct {
2224
Name string
2325
Description string
26+
Default string
2427
Type reflect.Type
28+
Index []int
2529
Fields []*Meta
2630
}
2731

@@ -93,6 +97,9 @@ func (m *Meta) Write(w io.Writer) error {
9397
buf.WriteString(" // ")
9498
buf.WriteString(field.Description)
9599
}
100+
if field.Default != "" {
101+
buf.WriteString(" (default: " + types.Quote(field.Default) + ")")
102+
}
96103

97104
buf.WriteString("\n")
98105
}
@@ -114,16 +121,20 @@ func (m *Meta) Validate(values any) error {
114121
}
115122

116123
func (m *Meta) New() server.Plugin {
117-
return reflect.New(m.Type).Interface().(server.Plugin)
124+
obj := reflect.New(m.Type)
125+
for _, field := range m.Fields {
126+
// Expand field for env
127+
setValue(obj.Elem().FieldByIndex(field.Index), os.ExpandEnv(field.Default))
128+
}
129+
return obj.Interface().(server.Plugin)
118130
}
119131

120132
////////////////////////////////////////////////////////////////////////////////
121133
// PRIVATE METHODS
122134

123135
func newMetaField(rf reflect.StructField) (*Meta, error) {
124136
meta := new(Meta)
125-
126-
//fmt.Println("newMetaField", rf.Name, rf.Type)
137+
meta.Index = rf.Index
127138

128139
// Name
129140
if name := nameForField(rf, "json", "yaml", "name"); name == "" {
@@ -134,7 +145,16 @@ func newMetaField(rf reflect.StructField) (*Meta, error) {
134145
}
135146

136147
// Description
137-
meta.Description = rf.Tag.Get("help")
148+
if description, _ := valueForField(rf, "description", "help"); description != "" {
149+
meta.Description = description
150+
}
151+
152+
// Env - needs to be an identififer
153+
if env, _ := valueForField(rf, "env"); types.IsIdentifier(env) {
154+
meta.Default = "${" + env + "}"
155+
} else if def, _ := valueForField(rf, "default"); def != "" {
156+
meta.Default = def
157+
}
138158

139159
// Type
140160
if t := typeName(rf.Type); t == "" {
@@ -152,6 +172,67 @@ var (
152172
durationType = reflect.TypeOf(time.Duration(0))
153173
)
154174

175+
func setValue(rv reflect.Value, str string) error {
176+
switch rv.Kind() {
177+
case reflect.Bool:
178+
// Zero value
179+
if str == "" {
180+
rv.SetZero()
181+
}
182+
// Bool
183+
if v, err := strconv.ParseBool(str); err != nil {
184+
return httpresponse.ErrBadRequest.Withf("invalid value for %s: %q", rv.Type(), str)
185+
} else {
186+
rv.SetBool(v)
187+
}
188+
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
189+
// Zero value
190+
if str == "" {
191+
rv.SetZero()
192+
}
193+
// Duration
194+
if rv.Type() == durationType {
195+
if v, err := time.ParseDuration(str); err != nil {
196+
return httpresponse.ErrBadRequest.Withf("invalid value for %s: %q", rv.Type(), str)
197+
} else {
198+
rv.Set(reflect.ValueOf(v))
199+
}
200+
}
201+
// Int
202+
if v, err := strconv.ParseInt(str, 10, 64); err != nil {
203+
return httpresponse.ErrBadRequest.Withf("invalid value for %s: %q", rv.Type(), str)
204+
} else {
205+
rv.SetInt(v)
206+
}
207+
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
208+
// Zero value
209+
if str == "" {
210+
rv.SetZero()
211+
}
212+
// Uint
213+
if v, err := strconv.ParseUint(str, 10, 64); err != nil {
214+
return httpresponse.ErrBadRequest.Withf("invalid value for %s: %q", rv.Type(), str)
215+
} else {
216+
rv.SetUint(v)
217+
}
218+
case reflect.Float32, reflect.Float64:
219+
// Zero value
220+
if str == "" {
221+
rv.SetZero()
222+
}
223+
// Float
224+
if v, err := strconv.ParseFloat(str, 64); err != nil {
225+
return httpresponse.ErrBadRequest.Withf("invalid value for %s: %q", rv.Type(), str)
226+
} else {
227+
rv.SetFloat(v)
228+
}
229+
case reflect.String:
230+
// String
231+
rv.SetString(str)
232+
}
233+
return httpresponse.ErrBadRequest.Withf("invalid value for %s: %q", rv.Type(), str)
234+
}
235+
155236
func typeName(rt reflect.Type) string {
156237
if rt.Kind() == reflect.Ptr {
157238
rt = rt.Elem()
@@ -189,20 +270,26 @@ func typeName(rt reflect.Type) string {
189270
return "ref"
190271
}
191272

192-
func nameForField(rt reflect.StructField, tags ...string) string {
273+
func valueForField(rf reflect.StructField, tags ...string) (string, bool) {
193274
for _, tag := range tags {
194-
tag, ok := rt.Tag.Lookup(tag)
275+
tag, ok := rf.Tag.Lookup(tag)
195276
if !ok {
196277
continue
197278
}
198-
if tag == "-" || tag == "" {
279+
if tag == "-" {
199280
// Ignore
200-
return ""
201-
}
202-
name := strings.Split(tag, ",")
203-
if len(name) > 0 && name[0] != "" {
204-
return name[0]
281+
return "", true
282+
} else {
283+
return tag, true
205284
}
206285
}
286+
return "", false
287+
}
288+
289+
func nameForField(rt reflect.StructField, tags ...string) string {
290+
value, exists := valueForField(rt, tags...)
291+
if exists {
292+
return value
293+
}
207294
return rt.Name
208295
}

0 commit comments

Comments
 (0)