From 98b8e8f8937391b0a9e8a4425fc13c3ed64d1ee6 Mon Sep 17 00:00:00 2001 From: Lavysh Alexander Date: Sat, 11 Mar 2023 19:48:49 +0800 Subject: [PATCH 1/9] Updated model of source in hasura config. --- config/config.go | 18 +++++++++++++++--- hasura/api.go | 12 +++++++----- hasura/hasura.go | 10 +++++----- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/config/config.go b/config/config.go index db3d944..1fdcfd7 100644 --- a/config/config.go +++ b/config/config.go @@ -54,16 +54,28 @@ type Database struct { type Hasura struct { URL string `yaml:"url" validate:"required,url"` Secret string `yaml:"admin_secret" validate:"required"` - Source string `yaml:"source" validate:"omitempty"` RowsLimit uint64 `yaml:"select_limit" validate:"gt=0"` EnableAggregations bool `yaml:"allow_aggregation"` AddSource bool `yaml:"add_source"` - Rest *bool `yaml:"rest"` + //Source string `yaml:"source" validate:"omitempty"` + Source *HasuraSource `yaml:"source" validate:"omitempty"` + Rest *bool `yaml:"rest"` +} + +type HasuraSource struct { + Name string `yaml:"name" validate:"required"` + DatabaseHost string `yaml:"database_host" validate:"omitempty"` + UsePreparedStatements bool `yaml:"use_prepared_statements"` + IsolationLevel string `yaml:"isolation_level"` } // UnmarshalYAML - func (h *Hasura) UnmarshalYAML(unmarshal func(interface{}) error) error { - h.Source = "default" + h.Source = &HasuraSource{ + Name: "default", + UsePreparedStatements: true, + IsolationLevel: "read-committed", + } type plain Hasura return unmarshal((*plain)(h)) diff --git a/hasura/api.go b/hasura/api.go index 170becb..9862dbc 100644 --- a/hasura/api.go +++ b/hasura/api.go @@ -66,7 +66,7 @@ func (api *API) get(ctx context.Context, endpoint string, args map[string]string return api.client.Do(req) } -//nolint +// nolint func (api *API) post(ctx context.Context, endpoint string, args map[string]string, body interface{}, output interface{}) error { url, err := api.buildURL(endpoint, args) if err != nil { @@ -124,15 +124,17 @@ func (api *API) Health(ctx context.Context) error { // AddSource - func (api *API) AddSource(ctx context.Context, hasura *config.Hasura, cfg config.Database) error { + databaseUrl := DatabaseUrl(fmt.Sprintf("postgresql://%s:%s@%s:%d/%s", cfg.User, cfg.Password, hasura.Source.DatabaseHost, cfg.Port, cfg.Database)) + req := Request{ Type: "pg_add_source", Args: map[string]interface{}{ - "name": hasura.Source, + "name": hasura.Source.Name, "configuration": Configuration{ ConnectionInfo: ConnectionInfo{ - DatabaseUrl: DatabaseUrl(fmt.Sprintf("postgresql://%s:%s@%s:%d/%s", cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.Database)), - UsePreparedStatements: true, - IsolationLevel: "read-committed", + DatabaseUrl: databaseUrl, + UsePreparedStatements: hasura.Source.UsePreparedStatements, // true + IsolationLevel: hasura.Source.IsolationLevel, // "read-committed" }, }, "replace_configuration": true, diff --git a/hasura/hasura.go b/hasura/hasura.go index d8fc8d0..cc340a3 100644 --- a/hasura/hasura.go +++ b/hasura/hasura.go @@ -85,7 +85,7 @@ func Create(ctx context.Context, args GenerateArgs) error { // Find our source in the existing metadata var selectedSource *Source = nil for idx := range export.Sources { - if export.Sources[idx].Name == args.Config.Source { + if export.Sources[idx].Name == args.Config.Source.Name { selectedSource = &export.Sources[idx] break } @@ -123,15 +123,15 @@ func Create(ctx context.Context, args GenerateArgs) error { log.Info().Msg("Tracking views...") for i := range args.Views { - if err := api.TrackTable(ctx, args.Views[i], args.Config.Source); err != nil { + if err := api.TrackTable(ctx, args.Views[i], args.Config.Source.Name); err != nil { if !strings.Contains(err.Error(), "view/table already tracked") { return err } } - if err := api.DropSelectPermissions(ctx, args.Views[i], args.Config.Source, "user"); err != nil { + if err := api.DropSelectPermissions(ctx, args.Views[i], args.Config.Source.Name, "user"); err != nil { log.Warn().Err(err).Msg("") } - if err := api.CreateSelectPermissions(ctx, args.Views[i], args.Config.Source, "user", Permission{ + if err := api.CreateSelectPermissions(ctx, args.Views[i], args.Config.Source.Name, "user", Permission{ Limit: args.Config.RowsLimit, AllowAggs: args.Config.EnableAggregations, Columns: Columns{"*"}, @@ -155,7 +155,7 @@ func Create(ctx context.Context, args GenerateArgs) error { func Generate(hasura config.Hasura, cfg config.Database, models ...interface{}) (*Metadata, error) { schema := getSchema(cfg) source := Source{ - Name: hasura.Source, + Name: hasura.Source.Name, Tables: make([]Table, 0), } for _, model := range models { From 7101f46df7d3bfd7f538a8d6bc7297b1ed09874e Mon Sep 17 00:00:00 2001 From: Lavysh Alexander Date: Sat, 11 Mar 2023 19:49:41 +0800 Subject: [PATCH 2/9] Updated .gitignore file. --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index b4929ab..485dc60 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ *.so *.dylib .env +.idea +.DS_Store # Test binary, built with `go test -c` *.test From 8f6b05b59de1ed17e35b179909bf3ab25f579836 Mon Sep 17 00:00:00 2001 From: Lavysh Alexander Date: Sat, 11 Mar 2023 19:59:41 +0800 Subject: [PATCH 3/9] Added fallback logic to db host as a source host in hasura config. --- hasura/api.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/hasura/api.go b/hasura/api.go index 9862dbc..e1494ac 100644 --- a/hasura/api.go +++ b/hasura/api.go @@ -124,7 +124,12 @@ func (api *API) Health(ctx context.Context) error { // AddSource - func (api *API) AddSource(ctx context.Context, hasura *config.Hasura, cfg config.Database) error { - databaseUrl := DatabaseUrl(fmt.Sprintf("postgresql://%s:%s@%s:%d/%s", cfg.User, cfg.Password, hasura.Source.DatabaseHost, cfg.Port, cfg.Database)) + host := cfg.Host + if hasura.Source.DatabaseHost != "" { + host = hasura.Source.DatabaseHost + } + + databaseUrl := DatabaseUrl(fmt.Sprintf("postgresql://%s:%s@%s:%d/%s", cfg.User, cfg.Password, host, cfg.Port, cfg.Database)) req := Request{ Type: "pg_add_source", @@ -133,8 +138,8 @@ func (api *API) AddSource(ctx context.Context, hasura *config.Hasura, cfg config "configuration": Configuration{ ConnectionInfo: ConnectionInfo{ DatabaseUrl: databaseUrl, - UsePreparedStatements: hasura.Source.UsePreparedStatements, // true - IsolationLevel: hasura.Source.IsolationLevel, // "read-committed" + UsePreparedStatements: hasura.Source.UsePreparedStatements, + IsolationLevel: hasura.Source.IsolationLevel, }, }, "replace_configuration": true, From c927d31086f01c8c56299c77c99621e4848dfd6a Mon Sep 17 00:00:00 2001 From: Lavysh Alexander Date: Sun, 12 Mar 2023 17:16:28 +0800 Subject: [PATCH 4/9] Remove unused comments, fixed tests and bug with reading Source as name. --- config/config.go | 15 +++++++-------- hasura/hasura.go | 2 +- hasura/hasura_test.go | 6 +++++- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/config/config.go b/config/config.go index 1fdcfd7..f8f7772 100644 --- a/config/config.go +++ b/config/config.go @@ -52,14 +52,13 @@ type Database struct { // Hasura - type Hasura struct { - URL string `yaml:"url" validate:"required,url"` - Secret string `yaml:"admin_secret" validate:"required"` - RowsLimit uint64 `yaml:"select_limit" validate:"gt=0"` - EnableAggregations bool `yaml:"allow_aggregation"` - AddSource bool `yaml:"add_source"` - //Source string `yaml:"source" validate:"omitempty"` - Source *HasuraSource `yaml:"source" validate:"omitempty"` - Rest *bool `yaml:"rest"` + URL string `yaml:"url" validate:"required,url"` + Secret string `yaml:"admin_secret" validate:"required"` + RowsLimit uint64 `yaml:"select_limit" validate:"gt=0"` + EnableAggregations bool `yaml:"allow_aggregation"` + AddSource bool `yaml:"add_source"` + Source *HasuraSource `yaml:"source" validate:"omitempty"` + Rest *bool `yaml:"rest"` } type HasuraSource struct { diff --git a/hasura/hasura.go b/hasura/hasura.go index cc340a3..c45cb19 100644 --- a/hasura/hasura.go +++ b/hasura/hasura.go @@ -91,7 +91,7 @@ func Create(ctx context.Context, args GenerateArgs) error { } } if selectedSource == nil { - return errors.Errorf("Source '%s' not found on exported metadata", args.Config.Source) + return errors.Errorf("Source '%s' not found on exported metadata", args.Config.Source.Name) } log.Info().Msg("Merging metadata...") diff --git a/hasura/hasura_test.go b/hasura/hasura_test.go index 65a05d1..26d316b 100644 --- a/hasura/hasura_test.go +++ b/hasura/hasura_test.go @@ -142,7 +142,11 @@ func TestGenerate(t *testing.T) { hasura: config.Hasura{ EnableAggregations: true, RowsLimit: 5, - Source: "mysql", + Source: &config.HasuraSource{ + Name: "mysql", + UsePreparedStatements: true, + IsolationLevel: "read-committed", + }, }, models: []interface{}{ &testTable{}, &testTable2{}, &testTable3{}, &testTable4{}, From 601cd0186c792d96e993746d7881fa0a7d547ffc Mon Sep 17 00:00:00 2001 From: Lavysh Alexander Date: Tue, 14 Mar 2023 14:54:23 +0800 Subject: [PATCH 5/9] Added required validation for flags in hasura config. --- config/config.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config/config.go b/config/config.go index f8f7772..f95d2a5 100644 --- a/config/config.go +++ b/config/config.go @@ -57,15 +57,15 @@ type Hasura struct { RowsLimit uint64 `yaml:"select_limit" validate:"gt=0"` EnableAggregations bool `yaml:"allow_aggregation"` AddSource bool `yaml:"add_source"` - Source *HasuraSource `yaml:"source" validate:"omitempty"` + Source *HasuraSource `yaml:"source"` Rest *bool `yaml:"rest"` } type HasuraSource struct { Name string `yaml:"name" validate:"required"` - DatabaseHost string `yaml:"database_host" validate:"omitempty"` - UsePreparedStatements bool `yaml:"use_prepared_statements"` - IsolationLevel string `yaml:"isolation_level"` + DatabaseHost string `yaml:"database_host"` + UsePreparedStatements bool `yaml:"use_prepared_statements" validate:"required"` + IsolationLevel string `yaml:"isolation_level" validate:"required"` } // UnmarshalYAML - From 4caf39da4d594254b7d5585c0511bb00cc783783 Mon Sep 17 00:00:00 2001 From: Lavysh Alexander Date: Tue, 14 Mar 2023 17:40:39 +0800 Subject: [PATCH 6/9] Added README fro hasura module with configuration description. Updated default values of hasura config. --- config/config.go | 4 ++-- hasura/README.md | 20 ++++++++++++++++++++ hasura/api.go | 7 ++++++- 3 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 hasura/README.md diff --git a/config/config.go b/config/config.go index f95d2a5..5616912 100644 --- a/config/config.go +++ b/config/config.go @@ -64,8 +64,8 @@ type Hasura struct { type HasuraSource struct { Name string `yaml:"name" validate:"required"` DatabaseHost string `yaml:"database_host"` - UsePreparedStatements bool `yaml:"use_prepared_statements" validate:"required"` - IsolationLevel string `yaml:"isolation_level" validate:"required"` + UsePreparedStatements bool `yaml:"use_prepared_statements"` + IsolationLevel string `yaml:"isolation_level"` } // UnmarshalYAML - diff --git a/hasura/README.md b/hasura/README.md new file mode 100644 index 0000000..c5dffe8 --- /dev/null +++ b/hasura/README.md @@ -0,0 +1,20 @@ +# Go wrapper for Hasura metadata methods + +Golang's library for registration data source in Hasura service + +## Configuration + +```yaml +hasura: + url: string # hasura url, required + admin_secret: string # required + select_limit: int + allow_aggregation: bool + source: + name: string # name of data source, required. For more info, [hasura docs](https://hasura.io/docs/latest/api-reference/metadata-api/source/#metadata-pg-add-source-syntax). + database_host: string # host of datasource, if omitted, used host from database config + use_prepared_statements: bool # if set to true the server prepares statement before executing on the source database (default: false) + isolation_level: bool # The transaction isolation level in which the queries made to the source will be run with (options: read-committed | repeatable-read | serializable) (default: read-committed) + add_source: bool # should data source be added? + rest: bool # should REST endpoints be created? +``` diff --git a/hasura/api.go b/hasura/api.go index e1494ac..5c4dd13 100644 --- a/hasura/api.go +++ b/hasura/api.go @@ -131,6 +131,11 @@ func (api *API) AddSource(ctx context.Context, hasura *config.Hasura, cfg config databaseUrl := DatabaseUrl(fmt.Sprintf("postgresql://%s:%s@%s:%d/%s", cfg.User, cfg.Password, host, cfg.Port, cfg.Database)) + isolationLevel := "read-committed" + if hasura.Source.IsolationLevel != "" { + isolationLevel = hasura.Source.IsolationLevel + } + req := Request{ Type: "pg_add_source", Args: map[string]interface{}{ @@ -139,7 +144,7 @@ func (api *API) AddSource(ctx context.Context, hasura *config.Hasura, cfg config ConnectionInfo: ConnectionInfo{ DatabaseUrl: databaseUrl, UsePreparedStatements: hasura.Source.UsePreparedStatements, - IsolationLevel: hasura.Source.IsolationLevel, + IsolationLevel: isolationLevel, }, }, "replace_configuration": true, From 8c60a02e63c13a664087a11393266cde554ab471 Mon Sep 17 00:00:00 2001 From: Lavysh Alexander Date: Tue, 14 Mar 2023 17:43:05 +0800 Subject: [PATCH 7/9] Updated main README with link to hasura module docs. --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 70083f7..a111f9e 100644 --- a/README.md +++ b/README.md @@ -233,4 +233,8 @@ head, err := tzkt.GetHead(ctx) if err != nil { log.Panic(err) } -``` \ No newline at end of file +``` + +### `hasura` + +Go wrapper for Hasura metadata methods, read docs [here](hasura/README.md) From f6e4b18d3f4e4b0a189ebda434fe40623224a96a Mon Sep 17 00:00:00 2001 From: Lavysh Alexander Date: Tue, 14 Mar 2023 19:43:03 +0800 Subject: [PATCH 8/9] Removed AddSource flag from hasura config. --- config/config.go | 1 - hasura/README.md | 1 - hasura/hasura.go | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/config/config.go b/config/config.go index 5616912..32a938b 100644 --- a/config/config.go +++ b/config/config.go @@ -56,7 +56,6 @@ type Hasura struct { Secret string `yaml:"admin_secret" validate:"required"` RowsLimit uint64 `yaml:"select_limit" validate:"gt=0"` EnableAggregations bool `yaml:"allow_aggregation"` - AddSource bool `yaml:"add_source"` Source *HasuraSource `yaml:"source"` Rest *bool `yaml:"rest"` } diff --git a/hasura/README.md b/hasura/README.md index c5dffe8..2f05f8a 100644 --- a/hasura/README.md +++ b/hasura/README.md @@ -15,6 +15,5 @@ hasura: database_host: string # host of datasource, if omitted, used host from database config use_prepared_statements: bool # if set to true the server prepares statement before executing on the source database (default: false) isolation_level: bool # The transaction isolation level in which the queries made to the source will be run with (options: read-committed | repeatable-read | serializable) (default: read-committed) - add_source: bool # should data source be added? rest: bool # should REST endpoints be created? ``` diff --git a/hasura/hasura.go b/hasura/hasura.go index c45cb19..73cb5ca 100644 --- a/hasura/hasura.go +++ b/hasura/hasura.go @@ -64,7 +64,7 @@ func Create(ctx context.Context, args GenerateArgs) error { checkHealth(ctx, api) - if args.Config.AddSource { + if args.Config.Source != nil { log.Info().Msg("Adding source...") if err := api.AddSource(ctx, args.Config, args.DatabaseConfig); err != nil { return err From 3487f43e708cd62e517410320d4e539e7a7bde76 Mon Sep 17 00:00:00 2001 From: Lavysh Alexander Date: Tue, 14 Mar 2023 19:43:45 +0800 Subject: [PATCH 9/9] Changed default value of UsePreparedStatements flag in hasura config. --- config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.go b/config/config.go index 32a938b..f52b4ec 100644 --- a/config/config.go +++ b/config/config.go @@ -71,7 +71,7 @@ type HasuraSource struct { func (h *Hasura) UnmarshalYAML(unmarshal func(interface{}) error) error { h.Source = &HasuraSource{ Name: "default", - UsePreparedStatements: true, + UsePreparedStatements: false, IsolationLevel: "read-committed", }