Browse Source

add json provider

pull/4/head
andrey 3 months ago
parent
commit
59f97e1681
  1. 19
      .drone.yml
  2. 17
      provider/json/fixture/config.json
  3. 13
      provider/json/go.mod
  4. 10
      provider/json/go.sum
  5. 65
      provider/json/provider.go
  6. 55
      provider/json/provider_example_test.go
  7. 33
      provider/json/provider_test.go

19
.drone.yml

@ -1,3 +1,4 @@
---
kind: pipeline
name: default
@ -11,10 +12,26 @@ steps:
image: golang
commands:
# - go test -parallel 10 -race ./...
# - go test -race ./...
- go test ./...
- name: golangci-lint
image: golangci/golangci-lint:v1.55
commands:
- golangci-lint run
---
kind: pipeline
name: json
steps:
- name: test
image: golang
commands:
- cd provider/json
- go test ./...
- name: golangci-lint
image: golangci/golangci-lint:v1.55
commands:
- cd provider/json
- golangci-lint run

17
provider/json/fixture/config.json

@ -0,0 +1,17 @@
{
"app": {
"name": {
"var": [
"name"
],
"title": "config title",
"timeout": "1m",
"success": true
}
},
"cfg": {
"duration": 1260000000000,
"enabled": true,
"type":"json"
}
}

13
provider/json/go.mod

@ -0,0 +1,13 @@
module gitoa.ru/go-4devs/config/provider/json
go 1.21
require (
github.com/tidwall/gjson v1.17.0
gitoa.ru/go-4devs/config v0.0.1
)
require (
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
)

10
provider/json/go.sum

@ -0,0 +1,10 @@
github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM=
github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
gitoa.ru/go-4devs/config v0.0.0-20240125174937-085589a9383a h1:61iwpn1Ec4yIkBSvSz8knNENJuhj6v2rp6bfw1wkG0E=
gitoa.ru/go-4devs/config v0.0.0-20240125174937-085589a9383a/go.mod h1:3g2bwE2OTDyYwm33KN/Cqc8pEdGlWXnB8Ju3PsYNQr0=
gitoa.ru/go-4devs/config v0.0.1 h1:9KrOO09YbIMO8qL8aVn/G74DurGdOIW5y3O02bays4I=
gitoa.ru/go-4devs/config v0.0.1/go.mod h1:xfEC2Al9xnMLJUuekYs3KhJ5BIzWAseNwkMwbN6/xss=

65
provider/json/provider.go

@ -0,0 +1,65 @@
package json
import (
"context"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/tidwall/gjson"
"gitoa.ru/go-4devs/config"
"gitoa.ru/go-4devs/config/value"
)
const (
Name = "json"
Separator = "."
)
var _ config.Provider = (*Provider)(nil)
func New(json []byte, opts ...Option) *Provider {
provider := Provider{
key: func(s ...string) string {
return strings.Join(s, Separator)
},
data: json,
}
for _, opt := range opts {
opt(&provider)
}
return &provider
}
func NewFile(path string, opts ...Option) (*Provider, error) {
file, err := os.ReadFile(filepath.Clean(path))
if err != nil {
return nil, fmt.Errorf("%w: unable to read config file %#q: file not found or unreadable", err, path)
}
return New(file, opts...), nil
}
type Option func(*Provider)
type Provider struct {
data []byte
key func(...string) string
name string
}
func (p *Provider) Name() string {
return p.name
}
func (p *Provider) Value(_ context.Context, path ...string) (config.Value, error) {
key := p.key(path...)
if val := gjson.GetBytes(p.data, key); val.Exists() {
return value.JString(val.String()), nil
}
return nil, fmt.Errorf("%v:%w", p.Name(), config.ErrValueNotFound)
}

55
provider/json/provider_example_test.go

@ -0,0 +1,55 @@
package json_test
import (
"context"
"fmt"
"log"
"gitoa.ru/go-4devs/config"
"gitoa.ru/go-4devs/config/provider/json"
"gitoa.ru/go-4devs/config/test"
)
func ExampleClient_Value() {
ctx := context.Background()
// read json config
jsonConfig, jerr := fixture.ReadFile("fixture/config.json")
if jerr != nil {
log.Printf("failed load file:%v", jerr)
return
}
config, err := config.New(
json.New(jsonConfig),
)
if err != nil {
log.Print(err)
return
}
title, err := config.Value(ctx, "app.name.title")
if err != nil {
log.Print("app.name.title", err)
return
}
cfgValue, err := config.Value(ctx, "cfg")
if err != nil {
log.Print("cfg ", err)
return
}
cfg := test.Config{}
_ = cfgValue.Unmarshal(&cfg)
fmt.Printf("title from json: %v\n", title.String())
fmt.Printf("struct from json: %+v\n", cfg)
// Output:
// title from json: config title
// struct from json: {Duration:21m0s Enabled:true}
}

33
provider/json/provider_test.go

@ -0,0 +1,33 @@
package json_test
import (
"embed"
"testing"
"time"
"gitoa.ru/go-4devs/config/provider/json"
"gitoa.ru/go-4devs/config/test"
"gitoa.ru/go-4devs/config/test/require"
)
//go:embed fixture/*
var fixture embed.FS
func TestProvider(t *testing.T) {
t.Parallel()
js, err := fixture.ReadFile("fixture/config.json")
require.NoError(t, err)
prov := json.New(js)
sl := []string{}
read := []test.Read{
test.NewRead("config title", "app.name.title"),
test.NewRead(time.Minute, "app.name.timeout"),
test.NewReadUnmarshal(&[]string{"name"}, &sl, "app.name.var"),
test.NewReadConfig("cfg"),
test.NewRead(true, "app", "name", "success"),
}
test.Run(t, prov, read)
}
Loading…
Cancel
Save