mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-09-20 15:09:02 +03:00
cli: improve error reporting in metadata apply
command
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4454 Co-authored-by: Aravind K P <8335904+scriptonist@users.noreply.github.com> GitOrigin-RevId: ae66bdfdc140c1a2a7747fb0ff2acd6f7b577d3f
This commit is contained in:
parent
132dffe4cf
commit
c668aa1158
@ -15,6 +15,7 @@ Event Triggers support has been added for MS SQL Server. Now, you can invoke ext
|
|||||||
- console: add GraphQL field customization for new database connections (root fields namespace, prefix, and suffix, and type names prefix and suffix)
|
- console: add GraphQL field customization for new database connections (root fields namespace, prefix, and suffix, and type names prefix and suffix)
|
||||||
- console: add support for mssql event triggers
|
- console: add support for mssql event triggers
|
||||||
- cli: fix perfomance regression with large metadata in `metadata apply`
|
- cli: fix perfomance regression with large metadata in `metadata apply`
|
||||||
|
- cli: fix error reporting in `metadata apply` command (#8280)
|
||||||
|
|
||||||
## v2.8.0
|
## v2.8.0
|
||||||
|
|
||||||
|
@ -461,7 +461,7 @@ func (a *ActionConfig) BaseDirectory() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *ActionConfig) GetActionsFileContent() (content types.Common, err error) {
|
func (a *ActionConfig) GetActionsFileContent() (content types.Common, err error) {
|
||||||
commonByt, err := ioutil.ReadFile(filepath.Join(a.MetadataDir, a.Filename()))
|
commonByt, err := metadataobject.ReadMetadataFile(filepath.Join(a.MetadataDir, a.Filename()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -470,7 +470,7 @@ func (a *ActionConfig) GetActionsFileContent() (content types.Common, err error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *ActionConfig) GetActionsGraphQLFileContent() (sdl string, err error) {
|
func (a *ActionConfig) GetActionsGraphQLFileContent() (sdl string, err error) {
|
||||||
commonByt, err := ioutil.ReadFile(filepath.Join(a.MetadataDir, graphqlFileName))
|
commonByt, err := metadataobject.ReadMetadataFile(filepath.Join(a.MetadataDir, graphqlFileName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ func (a *AllowListConfig) CreateFiles() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *AllowListConfig) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
func (a *AllowListConfig) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
||||||
data, err := ioutil.ReadFile(filepath.Join(a.MetadataDir, a.Filename()))
|
data, err := metadataobject.ReadMetadataFile(filepath.Join(a.MetadataDir, a.Filename()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, a.error(err)
|
return nil, a.error(err)
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ type apiLimitsObject struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *MetadataObject) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
func (o *MetadataObject) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
||||||
data, err := ioutil.ReadFile(filepath.Join(o.MetadataDir, o.Filename()))
|
data, err := metadataobject.ReadMetadataFile(filepath.Join(o.MetadataDir, o.Filename()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, o.error(err)
|
return nil, o.error(err)
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ func (c *CronTriggers) CreateFiles() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *CronTriggers) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
func (c *CronTriggers) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
||||||
data, err := ioutil.ReadFile(filepath.Join(c.MetadataDir, c.Filename()))
|
data, err := metadataobject.ReadMetadataFile(filepath.Join(c.MetadataDir, c.Filename()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, c.error(err)
|
return nil, c.error(err)
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ func (f *FunctionConfig) CreateFiles() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *FunctionConfig) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
func (f *FunctionConfig) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
||||||
data, err := ioutil.ReadFile(filepath.Join(f.MetadataDir, f.Filename()))
|
data, err := metadataobject.ReadMetadataFile(filepath.Join(f.MetadataDir, f.Filename()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, f.error(err)
|
return nil, f.error(err)
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ type graphQLSchemaIntrospectionObject struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *MetadataObject) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
func (o *MetadataObject) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
||||||
data, err := ioutil.ReadFile(filepath.Join(o.MetadataDir, o.Filename()))
|
data, err := metadataobject.ReadMetadataFile(filepath.Join(o.MetadataDir, o.Filename()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, o.error(err)
|
return nil, o.error(err)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package inheritedroles
|
package inheritedroles
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/hasura/graphql-engine/cli/v2/internal/metadataobject"
|
"github.com/hasura/graphql-engine/cli/v2/internal/metadataobject"
|
||||||
@ -36,7 +35,7 @@ func (ir *InheritedRolesConfig) CreateFiles() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ir *InheritedRolesConfig) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
func (ir *InheritedRolesConfig) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
||||||
data, err := ioutil.ReadFile(filepath.Join(ir.MetadataDir, ir.Filename()))
|
data, err := metadataobject.ReadMetadataFile(filepath.Join(ir.MetadataDir, ir.Filename()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ir.error(err)
|
return nil, ir.error(err)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -103,6 +104,16 @@ type Object interface {
|
|||||||
BaseDirectory() string
|
BaseDirectory() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ErrMetadataFileNotFound = fmt.Errorf("metadata file not found")
|
||||||
|
|
||||||
|
func ReadMetadataFile(filename string) ([]byte, error) {
|
||||||
|
bytes, err := ioutil.ReadFile(filename)
|
||||||
|
if err != nil && errors.Is(err, fs.ErrNotExist) {
|
||||||
|
return nil, ErrMetadataFileNotFound
|
||||||
|
}
|
||||||
|
return bytes, err
|
||||||
|
}
|
||||||
|
|
||||||
type ErrParsingMetadataObject interface {
|
type ErrParsingMetadataObject interface {
|
||||||
// ObjectName corresponds to metadata object in JSON format
|
// ObjectName corresponds to metadata object in JSON format
|
||||||
// eg: source, api_limits etc
|
// eg: source, api_limits etc
|
||||||
|
@ -47,7 +47,7 @@ type networkObject struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *NetworkObject) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
func (o *NetworkObject) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
||||||
data, err := ioutil.ReadFile(filepath.Join(o.MetadataDir, o.Filename()))
|
data, err := metadataobject.ReadMetadataFile(filepath.Join(o.MetadataDir, o.Filename()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, o.error(err)
|
return nil, o.error(err)
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ func (q *QueryCollectionConfig) CreateFiles() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (q *QueryCollectionConfig) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
func (q *QueryCollectionConfig) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
||||||
data, err := ioutil.ReadFile(filepath.Join(q.MetadataDir, q.Filename()))
|
data, err := metadataobject.ReadMetadataFile(filepath.Join(q.MetadataDir, q.Filename()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, q.error(err)
|
return nil, q.error(err)
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ func (r *RemoteSchemaConfig) CreateFiles() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (r *RemoteSchemaConfig) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
func (r *RemoteSchemaConfig) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
||||||
data, err := ioutil.ReadFile(filepath.Join(r.MetadataDir, r.Filename()))
|
data, err := metadataobject.ReadMetadataFile(filepath.Join(r.MetadataDir, r.Filename()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, r.error(err)
|
return nil, r.error(err)
|
||||||
}
|
}
|
||||||
@ -68,7 +68,7 @@ func (r *RemoteSchemaConfig) Build() (map[string]interface{}, metadataobject.Err
|
|||||||
}
|
}
|
||||||
|
|
||||||
type remoteSchema struct {
|
type remoteSchema struct {
|
||||||
Name yaml.Node `yaml:"name,omitempty"`
|
Name interface{} `yaml:"name,omitempty"`
|
||||||
Defintion yaml.Node `yaml:"definition,omitempty"`
|
Defintion yaml.Node `yaml:"definition,omitempty"`
|
||||||
Comment yaml.Node `yaml:"comment,omitempty"`
|
Comment yaml.Node `yaml:"comment,omitempty"`
|
||||||
Permissions []permission `yaml:"permissions,omitempty"`
|
Permissions []permission `yaml:"permissions,omitempty"`
|
||||||
@ -76,8 +76,8 @@ type remoteSchema struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type permission struct {
|
type permission struct {
|
||||||
Role yaml.Node `yaml:"role,omitempty"`
|
Role interface{} `yaml:"role,omitempty"`
|
||||||
Definition definition `yaml:"definition,omitempty"`
|
Definition definition `yaml:"definition,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type definition struct {
|
type definition struct {
|
||||||
|
@ -45,7 +45,7 @@ func (re *RestEndpointsConfig) CreateFiles() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (re *RestEndpointsConfig) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
func (re *RestEndpointsConfig) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
||||||
data, err := ioutil.ReadFile(filepath.Join(re.MetadataDir, re.Filename()))
|
data, err := metadataobject.ReadMetadataFile(filepath.Join(re.MetadataDir, re.Filename()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, re.error(err)
|
return nil, re.error(err)
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ func (t *SourceConfig) CreateFiles() error {
|
|||||||
|
|
||||||
func (t *SourceConfig) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
func (t *SourceConfig) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
||||||
sourceFile := filepath.Join(t.MetadataDir, sourcesDirectory, t.Filename())
|
sourceFile := filepath.Join(t.MetadataDir, sourcesDirectory, t.Filename())
|
||||||
sourcesBytes, err := ioutil.ReadFile(sourceFile)
|
sourcesBytes, err := metadataobject.ReadMetadataFile(sourceFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, t.error(err)
|
return nil, t.error(err)
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ func (t *TableConfig) CreateFiles() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *TableConfig) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
func (t *TableConfig) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
||||||
data, err := ioutil.ReadFile(filepath.Join(t.MetadataDir, t.Filename()))
|
data, err := metadataobject.ReadMetadataFile(filepath.Join(t.MetadataDir, t.Filename()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, t.error(err)
|
return nil, t.error(err)
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ func (a *VersionConfig) CreateFiles() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *VersionConfig) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
func (a *VersionConfig) Build() (map[string]interface{}, metadataobject.ErrParsingMetadataObject) {
|
||||||
data, err := ioutil.ReadFile(filepath.Join(a.MetadataDir, a.Filename()))
|
data, err := metadataobject.ReadMetadataFile(filepath.Join(a.MetadataDir, a.Filename()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, a.error(err)
|
return nil, a.error(err)
|
||||||
}
|
}
|
||||||
|
@ -61,18 +61,38 @@ func (f *fragment) UnmarshalYAML(value *yaml.Node) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var resolver = func(ctx map[string]string, node *yaml.Node, files *[]string) (*yaml.Node, error) {
|
type YamlTagResolverError struct {
|
||||||
if node.Kind != yaml.ScalarNode {
|
tag string
|
||||||
return nil, fmt.Errorf("found %s on scalar node", baseDirectoryKey)
|
file string
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *YamlTagResolverError) Error() string {
|
||||||
|
if e.tag == "" {
|
||||||
|
return fmt.Sprintf("yaml tag resolver error: %s", e.err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"yaml tag resolver error:\ntag: %s\nfile: %s\nerror: %s",
|
||||||
|
e.tag,
|
||||||
|
e.file,
|
||||||
|
e.err.Error(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *YamlTagResolverError) Unwrap() error {
|
||||||
|
return e.err
|
||||||
|
}
|
||||||
|
|
||||||
|
var resolver = func(ctx map[string]string, node *yaml.Node, files *[]string) (*yaml.Node, error) {
|
||||||
baseDir, ok := ctx[baseDirectoryKey]
|
baseDir, ok := ctx[baseDirectoryKey]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("parser error: base directory for !include tag not specified")
|
return nil, &YamlTagResolverError{"", "", fmt.Errorf("parser error: base directory for !include tag not specified")}
|
||||||
}
|
}
|
||||||
fileLocation := filepath.Join(baseDir, node.Value)
|
fileLocation := filepath.Join(baseDir, node.Value)
|
||||||
file, err := ioutil.ReadFile(fileLocation)
|
file, err := ioutil.ReadFile(fileLocation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s: %w", fileLocation, err)
|
return nil, &YamlTagResolverError{node.Tag, fileLocation, err}
|
||||||
}
|
}
|
||||||
if files != nil {
|
if files != nil {
|
||||||
*files = append(*files, fileLocation)
|
*files = append(*files, fileLocation)
|
||||||
@ -89,12 +109,23 @@ var resolver = func(ctx map[string]string, node *yaml.Node, files *[]string) (*y
|
|||||||
var f = newFragment(newctx, files)
|
var f = newFragment(newctx, files)
|
||||||
err = yaml.Unmarshal(file, f)
|
err = yaml.Unmarshal(file, f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s: %w", fileLocation, err)
|
return nil, &YamlTagResolverError{node.Tag, fileLocation, err}
|
||||||
}
|
}
|
||||||
return f.content, nil
|
return f.content, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveTags(ctx map[string]string, node *yaml.Node, files *[]string) (*yaml.Node, error) {
|
func resolveTags(ctx map[string]string, node *yaml.Node, files *[]string) (*yaml.Node, error) {
|
||||||
|
switch node.Kind {
|
||||||
|
case yaml.DocumentNode, yaml.SequenceNode, yaml.MappingNode:
|
||||||
|
var err error
|
||||||
|
for idx := range node.Content {
|
||||||
|
node.Content[idx], err = resolveTags(ctx, node.Content[idx], files)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch node.Tag {
|
switch node.Tag {
|
||||||
case includeTag:
|
case includeTag:
|
||||||
return resolver(ctx, node, files)
|
return resolver(ctx, node, files)
|
||||||
@ -107,16 +138,6 @@ func resolveTags(ctx map[string]string, node *yaml.Node, files *[]string) (*yaml
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch node.Kind {
|
|
||||||
case yaml.DocumentNode, yaml.SequenceNode, yaml.MappingNode:
|
|
||||||
var err error
|
|
||||||
for idx := range node.Content {
|
|
||||||
node.Content[idx], err = resolveTags(ctx, node.Content[idx], files)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return node, nil
|
return node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -115,7 +114,7 @@ func (h *Handler) buildMetadataMap() (map[string]interface{}, error) {
|
|||||||
for _, object := range h.objects {
|
for _, object := range h.objects {
|
||||||
objectMetadata, err := object.Build()
|
objectMetadata, err := object.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, fs.ErrNotExist) {
|
if errors.Is(err, metadataobject.ErrMetadataFileNotFound) {
|
||||||
h.logger.Debugf("metadata file for %s was not found, assuming an empty file", object.Key())
|
h.logger.Debugf("metadata file for %s was not found, assuming an empty file", object.Key())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user