mirror of
https://github.com/zhigang1992/graphql-engine.git
synced 2026-06-15 01:59:08 +08:00
242 lines
5.2 KiB
Go
242 lines
5.2 KiB
Go
package hasuradb
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
gyaml "github.com/ghodss/yaml"
|
|
"github.com/hasura/graphql-engine/cli/metadata/types"
|
|
"github.com/hasura/graphql-engine/cli/migrate/database"
|
|
"github.com/pkg/errors"
|
|
"gopkg.in/yaml.v2"
|
|
|
|
"github.com/oliveagle/jsonpath"
|
|
)
|
|
|
|
func (h *HasuraDB) SetMetadataPlugins(plugins types.MetadataPlugins) {
|
|
h.config.Plugins = plugins
|
|
}
|
|
|
|
func (h *HasuraDB) ExportMetadata() (map[string][]byte, error) {
|
|
query := HasuraQuery{
|
|
Type: "export_metadata",
|
|
Args: HasuraArgs{},
|
|
}
|
|
|
|
resp, body, err := h.sendv1Query(query)
|
|
if err != nil {
|
|
h.logger.Debug(err)
|
|
return nil, err
|
|
}
|
|
h.logger.Debug("response: ", string(body))
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return nil, NewHasuraError(body, h.config.isCMD)
|
|
}
|
|
|
|
var c yaml.MapSlice
|
|
err = yaml.Unmarshal(body, &c)
|
|
if err != nil {
|
|
h.logger.Debug(err)
|
|
return nil, err
|
|
}
|
|
|
|
metadataFiles := make(map[string][]byte)
|
|
for _, plg := range h.config.Plugins {
|
|
files, err := plg.Export(c)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, fmt.Sprintf("cannot export %s from metadata", plg.Name()))
|
|
}
|
|
for fileName, content := range files {
|
|
metadataFiles[fileName] = content
|
|
}
|
|
}
|
|
return metadataFiles, nil
|
|
}
|
|
|
|
func (h *HasuraDB) ResetMetadata() error {
|
|
query := HasuraInterfaceQuery{
|
|
Type: "clear_metadata",
|
|
Args: HasuraArgs{},
|
|
}
|
|
|
|
resp, body, err := h.sendv1Query(query)
|
|
if err != nil {
|
|
h.logger.Debug(err)
|
|
return err
|
|
}
|
|
h.logger.Debug("response: ", string(body))
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return NewHasuraError(body, h.config.isCMD)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ReloadMetadata - Reload Hasura GraphQL Engine metadata on the database
|
|
func (h *HasuraDB) ReloadMetadata() error {
|
|
query := HasuraInterfaceQuery{
|
|
Type: "reload_metadata",
|
|
Args: HasuraArgs{},
|
|
}
|
|
|
|
resp, body, err := h.sendv1Query(query)
|
|
if err != nil {
|
|
h.logger.Debug(err)
|
|
return err
|
|
}
|
|
h.logger.Debug("response: ", string(body))
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return NewHasuraError(body, h.config.isCMD)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (h *HasuraDB) GetInconsistentMetadata() (bool, []database.InconsistentMetadataInterface, error) {
|
|
query := HasuraInterfaceQuery{
|
|
Type: "get_inconsistent_metadata",
|
|
Args: HasuraArgs{},
|
|
}
|
|
|
|
resp, body, err := h.sendv1Query(query)
|
|
if err != nil {
|
|
h.logger.Debug(err)
|
|
return false, nil, err
|
|
}
|
|
h.logger.Debug("response: ", string(body))
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return false, nil, NewHasuraError(body, h.config.isCMD)
|
|
}
|
|
|
|
var inMet InconsistentMetadata
|
|
err = json.Unmarshal(body, &inMet)
|
|
if err != nil {
|
|
return false, nil, err
|
|
}
|
|
inMetInterface := make([]database.InconsistentMetadataInterface, 0)
|
|
for _, obj := range inMet.InConsistentObjects {
|
|
inMetInterface = append(inMetInterface, database.InconsistentMetadataInterface(obj))
|
|
}
|
|
return inMet.IsConsistent, inMetInterface, nil
|
|
}
|
|
|
|
func (h *HasuraDB) DropInconsistentMetadata() error {
|
|
query := HasuraInterfaceQuery{
|
|
Type: "drop_inconsistent_metadata",
|
|
Args: HasuraArgs{},
|
|
}
|
|
|
|
resp, body, err := h.sendv1Query(query)
|
|
if err != nil {
|
|
h.logger.Debug(err)
|
|
return err
|
|
}
|
|
h.logger.Debug("response: ", string(body))
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return NewHasuraError(body, h.config.isCMD)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (h *HasuraDB) BuildMetadata() (yaml.MapSlice, error) {
|
|
var tmpMeta yaml.MapSlice
|
|
for _, plg := range h.config.Plugins {
|
|
err := plg.Build(&tmpMeta)
|
|
if err != nil {
|
|
return tmpMeta, errors.Wrap(err, fmt.Sprintf("cannot build %s from metadata", plg.Name()))
|
|
}
|
|
}
|
|
return tmpMeta, nil
|
|
}
|
|
|
|
func (h *HasuraDB) ApplyMetadata() error {
|
|
tmpMeta, err := h.BuildMetadata()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
yByt, err := yaml.Marshal(tmpMeta)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
jbyt, err := gyaml.YAMLToJSON(yByt)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var obj interface{}
|
|
err = json.Unmarshal(jbyt, &obj)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
query := HasuraInterfaceBulk{
|
|
Type: "bulk",
|
|
Args: []interface{}{
|
|
HasuraInterfaceQuery{
|
|
Type: "clear_metadata",
|
|
Args: HasuraArgs{},
|
|
},
|
|
HasuraInterfaceQuery{
|
|
Type: "replace_metadata",
|
|
Args: obj,
|
|
},
|
|
},
|
|
}
|
|
resp, body, err := h.sendv1Query(query)
|
|
if err != nil {
|
|
h.logger.Debug(err)
|
|
return err
|
|
}
|
|
h.logger.Debug("response: ", string(body))
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
switch herror := NewHasuraError(body, h.config.isCMD).(type) {
|
|
case HasuraError:
|
|
if herror.Path != "" {
|
|
jsonData, err := json.Marshal(query)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var metadataQuery interface{}
|
|
err = json.Unmarshal(jsonData, &metadataQuery)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
lookup, err := jsonpath.JsonPathLookup(metadataQuery, herror.Path)
|
|
if err == nil {
|
|
queryData, err := json.MarshalIndent(lookup, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
herror.migrationQuery = "offending object: \n\r\n\r" + string(queryData)
|
|
}
|
|
}
|
|
return herror
|
|
default:
|
|
return herror
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (h *HasuraDB) Query(data interface{}) error {
|
|
query := HasuraInterfaceQuery{
|
|
Type: "bulk",
|
|
Args: data,
|
|
}
|
|
|
|
resp, body, err := h.sendv1Query(query)
|
|
if err != nil {
|
|
h.logger.Debug(err)
|
|
return err
|
|
}
|
|
h.logger.Debug("response: ", string(body))
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return NewHasuraError(body, h.config.isCMD)
|
|
}
|
|
return nil
|
|
}
|