cli: wrap errors

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/3146
GitOrigin-RevId: 5dd78bf9145d3bfc9ff4281239d849e796a36246
This commit is contained in:
Aravind K P 2021-12-15 23:24:47 +05:30 committed by hasura-bot
parent 37ecb0e3b2
commit 96cfacb58b
15 changed files with 195 additions and 90 deletions

View File

@ -53,7 +53,6 @@ import (
"github.com/hasura/graphql-engine/cli/v2/telemetry" "github.com/hasura/graphql-engine/cli/v2/telemetry"
"github.com/hasura/graphql-engine/cli/v2/util" "github.com/hasura/graphql-engine/cli/v2/util"
"github.com/hasura/graphql-engine/cli/v2/version" "github.com/hasura/graphql-engine/cli/v2/version"
"github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/subosito/gotenv" "github.com/subosito/gotenv"
@ -204,7 +203,7 @@ func (c *ServerConfig) GetHasuraInternalServerConfig() error {
client := http.Client{Timeout: 30 * time.Second} client := http.Client{Timeout: 30 * time.Second}
req, err := http.NewRequest("GET", url, nil) req, err := http.NewRequest("GET", url, nil)
if err != nil { if err != nil {
return errors.Wrap(err, "error fetching config from server") return fmt.Errorf("error fetching config from server: %w", err)
} }
if c.AdminSecret != "" { if c.AdminSecret != "" {
@ -307,10 +306,10 @@ func (s *ServerConfig) SetTLSConfig() error {
certPath, _ := filepath.Abs(s.CAPath) certPath, _ := filepath.Abs(s.CAPath)
cert, err := ioutil.ReadFile(certPath) cert, err := ioutil.ReadFile(certPath)
if err != nil { if err != nil {
return errors.Errorf("error reading CA %s", s.CAPath) return fmt.Errorf("error reading CA %s: %w", s.CAPath, err)
} }
if ok := rootCAs.AppendCertsFromPEM(cert); !ok { if ok := rootCAs.AppendCertsFromPEM(cert); !ok {
return errors.Errorf("Unable to append given CA cert.") return fmt.Errorf("unable to append given CA cert")
} }
s.TLSConfig = &tls.Config{ s.TLSConfig = &tls.Config{
RootCAs: rootCAs, RootCAs: rootCAs,
@ -516,7 +515,7 @@ func (ec *ExecutionContext) Prepare() error {
// setup global config // setup global config
err := ec.setupGlobalConfig() err := ec.setupGlobalConfig()
if err != nil { if err != nil {
return errors.Wrap(err, "setting up global config failed") return fmt.Errorf("setting up global config failed: %w", err)
} }
if !ec.proPluginVersionValidated { if !ec.proPluginVersionValidated {
@ -554,7 +553,7 @@ func (ec *ExecutionContext) SetupPlugins() error {
base := filepath.Join(ec.GlobalConfigDir, "plugins") base := filepath.Join(ec.GlobalConfigDir, "plugins")
base, err := filepath.Abs(base) base, err := filepath.Abs(base)
if err != nil { if err != nil {
return errors.Wrap(err, "cannot get absolute path") return fmt.Errorf("cannot get absolute path: %w", err)
} }
ec.PluginsConfig = plugins.New(base) ec.PluginsConfig = plugins.New(base)
ec.PluginsConfig.Logger = ec.Logger ec.PluginsConfig.Logger = ec.Logger
@ -594,7 +593,7 @@ func (ec *ExecutionContext) SetupCodegenAssetsRepo() error {
base := filepath.Join(ec.GlobalConfigDir, util.ActionsCodegenDirName) base := filepath.Join(ec.GlobalConfigDir, util.ActionsCodegenDirName)
base, err := filepath.Abs(base) base, err := filepath.Abs(base)
if err != nil { if err != nil {
return errors.Wrap(err, "cannot get absolute path") return fmt.Errorf("cannot get absolute path: %w", err)
} }
ec.CodegenAssetsRepo = util.NewGitUtil(util.ActionsCodegenRepoURI, base, "") ec.CodegenAssetsRepo = util.NewGitUtil(util.ActionsCodegenRepoURI, base, "")
ec.CodegenAssetsRepo.Logger = ec.Logger ec.CodegenAssetsRepo.Logger = ec.Logger
@ -621,7 +620,7 @@ func (ec *ExecutionContext) Validate() error {
// load .env file // load .env file
err = ec.loadEnvfile() err = ec.loadEnvfile()
if err != nil { if err != nil {
return errors.Wrap(err, "loading .env file failed") return fmt.Errorf("loading .env file failed: %w", err)
} }
// set names of config file // set names of config file
@ -630,7 +629,7 @@ func (ec *ExecutionContext) Validate() error {
// read config and parse the values into Config // read config and parse the values into Config
err = ec.readConfig() err = ec.readConfig()
if err != nil { if err != nil {
return errors.Wrap(err, "cannot read config") return fmt.Errorf("cannot read config: %w", err)
} }
// set name of migration directory // set name of migration directory
@ -638,7 +637,7 @@ func (ec *ExecutionContext) Validate() error {
if _, err := os.Stat(ec.MigrationDir); os.IsNotExist(err) { if _, err := os.Stat(ec.MigrationDir); os.IsNotExist(err) {
err = os.MkdirAll(ec.MigrationDir, os.ModePerm) err = os.MkdirAll(ec.MigrationDir, os.ModePerm)
if err != nil { if err != nil {
return errors.Wrap(err, "cannot create migrations directory") return fmt.Errorf("cannot create migrations directory: %w", err)
} }
} }
@ -646,7 +645,7 @@ func (ec *ExecutionContext) Validate() error {
if _, err := os.Stat(ec.SeedsDirectory); os.IsNotExist(err) { if _, err := os.Stat(ec.SeedsDirectory); os.IsNotExist(err) {
err = os.MkdirAll(ec.SeedsDirectory, os.ModePerm) err = os.MkdirAll(ec.SeedsDirectory, os.ModePerm)
if err != nil { if err != nil {
return errors.Wrap(err, "cannot create seeds directory") return fmt.Errorf("cannot create seeds directory: %w", err)
} }
} }
@ -672,7 +671,7 @@ func (ec *ExecutionContext) Validate() error {
if _, err := os.Stat(ec.MetadataDir); os.IsNotExist(err) && !(len(ec.MetadataFile) > 0) { if _, err := os.Stat(ec.MetadataDir); os.IsNotExist(err) && !(len(ec.MetadataFile) > 0) {
err = os.MkdirAll(ec.MetadataDir, os.ModePerm) err = os.MkdirAll(ec.MetadataDir, os.ModePerm)
if err != nil { if err != nil {
return errors.Wrap(err, "cannot create metadata directory") return fmt.Errorf("cannot create metadata directory: %w", err)
} }
} }
} }
@ -700,13 +699,13 @@ func (ec *ExecutionContext) Validate() error {
// get version from the server and match with the cli version // get version from the server and match with the cli version
err = ec.checkServerVersion() err = ec.checkServerVersion()
if err != nil { if err != nil {
return errors.Wrap(err, "version check") return fmt.Errorf("version check: %w", err)
} }
// get the server feature flags // get the server feature flags
err = ec.Version.GetServerFeatureFlags() err = ec.Version.GetServerFeatureFlags()
if err != nil { if err != nil {
return errors.Wrap(err, "error in getting server feature flags") return fmt.Errorf("error in getting server feature flags %w", err)
} }
var headers map[string]string var headers map[string]string
if ec.Config.AdminSecret != "" { if ec.Config.AdminSecret != "" {
@ -762,9 +761,9 @@ func (ec *ExecutionContext) Validate() error {
} }
var state *util.ServerState var state *util.ServerState
if ec.HasMetadataV3 { if ec.HasMetadataV3 {
state = util.GetServerState(ec.Config.GetV1MetadataEndpoint(), ec.Config.ServerConfig.AdminSecret, ec.Config.ServerConfig.TLSConfig, ec.HasMetadataV3, ec.Logger) state = util.GetServerState(httpClient, ec.Config.GetV1MetadataEndpoint(), ec.HasMetadataV3, ec.Logger)
} else { } else {
state = util.GetServerState(ec.Config.GetV1QueryEndpoint(), ec.Config.ServerConfig.AdminSecret, ec.Config.ServerConfig.TLSConfig, ec.HasMetadataV3, ec.Logger) state = util.GetServerState(httpClient, ec.Config.GetV1QueryEndpoint(), ec.HasMetadataV3, ec.Logger)
} }
ec.ServerUUID = state.UUID ec.ServerUUID = state.UUID
ec.Telemetry.ServerUUID = ec.ServerUUID ec.Telemetry.ServerUUID = ec.ServerUUID
@ -776,7 +775,7 @@ func (ec *ExecutionContext) Validate() error {
func (ec *ExecutionContext) checkServerVersion() error { func (ec *ExecutionContext) checkServerVersion() error {
v, err := version.FetchServerVersion(ec.Config.ServerConfig.GetVersionEndpoint(), ec.Config.ServerConfig.HTTPClient) v, err := version.FetchServerVersion(ec.Config.ServerConfig.GetVersionEndpoint(), ec.Config.ServerConfig.HTTPClient)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to get version from server") return fmt.Errorf("failed to get version from server: %w", err)
} }
ec.Version.SetServerVersion(v) ec.Version.SetServerVersion(v)
ec.Telemetry.ServerVersion = ec.Version.GetServerVersion() ec.Telemetry.ServerVersion = ec.Version.GetServerVersion()
@ -837,7 +836,7 @@ func (ec *ExecutionContext) readConfig() error {
v.AddConfigPath(ec.ExecutionDirectory) v.AddConfigPath(ec.ExecutionDirectory)
err := v.ReadInConfig() err := v.ReadInConfig()
if err != nil { if err != nil {
return errors.Wrap(err, "cannot read config from file/env") return fmt.Errorf("cannot read config from file/env: %w", err)
} }
adminSecret := v.GetString("admin_secret") adminSecret := v.GetString("admin_secret")
if adminSecret == "" { if adminSecret == "" {
@ -881,7 +880,7 @@ func (ec *ExecutionContext) readConfig() error {
} }
err = ec.Config.ServerConfig.ParseEndpoint() err = ec.Config.ServerConfig.ParseEndpoint()
if err != nil { if err != nil {
return errors.Wrap(err, "unable to parse server endpoint") return fmt.Errorf("unable to parse server endpoint: %w", err)
} }
// this populates the ec.Config.ServerConfig.HasuraServerInternalConfig // this populates the ec.Config.ServerConfig.HasuraServerInternalConfig
@ -893,7 +892,7 @@ func (ec *ExecutionContext) readConfig() error {
err = ec.Config.ServerConfig.SetTLSConfig() err = ec.Config.ServerConfig.SetTLSConfig()
if err != nil { if err != nil {
return errors.Wrap(err, "setting up TLS config failed") return fmt.Errorf("setting up TLS config failed: %w", err)
} }
return ec.Config.ServerConfig.SetHTTPClient() return ec.Config.ServerConfig.SetHTTPClient()
} }

View File

@ -71,7 +71,7 @@ func (o *actionsCreateOptions) run() error {
o.EC.Spin("Deriving a Hasura operation...") o.EC.Spin("Deriving a Hasura operation...")
introSchema, err = o.EC.APIClient.V1Graphql.GetIntrospectionSchema() introSchema, err = o.EC.APIClient.V1Graphql.GetIntrospectionSchema()
if err != nil { if err != nil {
return errors.Wrap(err, "error in fetching introspection schema") return fmt.Errorf("error in fetching introspection schema: %w", err)
} }
o.EC.Spinner.Stop() o.EC.Spinner.Stop()
} }

View File

@ -12,7 +12,6 @@ import (
goyaml "github.com/goccy/go-yaml" goyaml "github.com/goccy/go-yaml"
"github.com/hasura/graphql-engine/cli/v2" "github.com/hasura/graphql-engine/cli/v2"
"github.com/hasura/graphql-engine/cli/v2/internal/projectmetadata" "github.com/hasura/graphql-engine/cli/v2/internal/projectmetadata"
"github.com/pkg/errors"
) )
type MetadataModeHandler interface { type MetadataModeHandler interface {
@ -39,11 +38,11 @@ func (m *metadataModeDirectoryHandler) Export(o *MetadataExportOptions) error {
files, err := metadataHandler.ExportMetadata() files, err := metadataHandler.ExportMetadata()
o.EC.Spinner.Stop() o.EC.Spinner.Stop()
if err != nil { if err != nil {
return errors.Wrap(err, "failed to export metadata") return fmt.Errorf("failed to export metadata: %w", err)
} }
err = metadataHandler.WriteMetadata(files) err = metadataHandler.WriteMetadata(files)
if err != nil { if err != nil {
return errors.Wrap(err, "cannot write metadata to project") return fmt.Errorf("cannot write metadata to project: %w", err)
} }
return nil return nil
} }

View File

@ -6,7 +6,6 @@ import (
"github.com/hasura/graphql-engine/cli/v2/internal/projectmetadata" "github.com/hasura/graphql-engine/cli/v2/internal/projectmetadata"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/hasura/graphql-engine/cli/v2" "github.com/hasura/graphql-engine/cli/v2"
@ -27,7 +26,7 @@ func newMetadataInconsistencyListCmd(ec *cli.ExecutionContext) *cobra.Command {
err := opts.run() err := opts.run()
opts.EC.Spinner.Stop() opts.EC.Spinner.Stop()
if err != nil { if err != nil {
return errors.Wrap(err, "failed to list inconsistent metadata") return fmt.Errorf("failed to list inconsistent metadata: %w", err)
} }
if opts.isConsistent { if opts.isConsistent {
opts.EC.Logger.Println("metadata is consistent") opts.EC.Logger.Println("metadata is consistent")

View File

@ -6,7 +6,6 @@ import (
"github.com/hasura/graphql-engine/cli/v2" "github.com/hasura/graphql-engine/cli/v2"
"github.com/hasura/graphql-engine/cli/v2/internal/projectmetadata" "github.com/hasura/graphql-engine/cli/v2/internal/projectmetadata"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -44,7 +43,7 @@ func (o *MetadataReloadOptions) runWithInfo() error {
err := o.run() err := o.run()
o.EC.Spinner.Stop() o.EC.Spinner.Stop()
if err != nil { if err != nil {
return errors.Wrap(err, "failed to reload metadata") return fmt.Errorf("failed to reload metadata: %w", err)
} }
o.EC.Logger.Info("Metadata reloaded") o.EC.Logger.Info("Metadata reloaded")
icListOpts := &metadataInconsistencyListOptions{ icListOpts := &metadataInconsistencyListOptions{
@ -52,7 +51,7 @@ func (o *MetadataReloadOptions) runWithInfo() error {
} }
err = icListOpts.read(projectmetadata.NewHandlerFromEC(icListOpts.EC)) err = icListOpts.read(projectmetadata.NewHandlerFromEC(icListOpts.EC))
if err != nil { if err != nil {
return fmt.Errorf("failed to read metadata status: %v", err) return fmt.Errorf("failed to read metadata status: %w", err)
} }
if icListOpts.isConsistent { if icListOpts.isConsistent {
icListOpts.EC.Logger.Infoln("Metadata is consistent") icListOpts.EC.Logger.Infoln("Metadata is consistent")
@ -67,7 +66,7 @@ func (o *MetadataReloadOptions) run() error {
metadataHandler := projectmetadata.NewHandlerFromEC(o.EC) metadataHandler := projectmetadata.NewHandlerFromEC(o.EC)
_, err = metadataHandler.ReloadMetadata() _, err = metadataHandler.ReloadMetadata()
if err != nil { if err != nil {
return errors.Wrap(err, "Cannot reload metadata") return fmt.Errorf("cannot reload metadata: %w", err)
} }
return nil return nil
} }

View File

@ -198,7 +198,7 @@ func (o *MigrateApplyOptions) Apply() (chan MigrateApplyResult, error) {
// if so skip this // if so skip this
return "", fmt.Errorf("skipping applying migrations on database %s, encountered: \n%s", o.Source.Name, e.Error()) return "", fmt.Errorf("skipping applying migrations on database %s, encountered: \n%s", o.Source.Name, e.Error())
} else if err != nil { } else if err != nil {
return "", fmt.Errorf("skipping applying migrations on database %s, encountered: \n%v", o.Source.Name, err) return "", fmt.Errorf("skipping applying migrations on database %s, encountered: \n%w", o.Source.Name, err)
} }
return "", nil return "", nil
} }

View File

@ -19,7 +19,7 @@ import (
func YamlDiff(fromFile, toFile ytbx.InputFile, writer io.Writer, fileName string) (int, error) { func YamlDiff(fromFile, toFile ytbx.InputFile, writer io.Writer, fileName string) (int, error) {
report, err := dyff.CompareInputFiles(fromFile, toFile, dyff.IgnoreOrderChanges(true)) report, err := dyff.CompareInputFiles(fromFile, toFile, dyff.IgnoreOrderChanges(true))
if err != nil { if err != nil {
return -1, fmt.Errorf("error while getting diff: %v", err) return -1, fmt.Errorf("error while getting diff: %w", err)
} }
reportWriter := &dyff.HumanReport{ reportWriter := &dyff.HumanReport{
Report: report, Report: report,
@ -32,7 +32,7 @@ func YamlDiff(fromFile, toFile ytbx.InputFile, writer io.Writer, fileName string
fmt.Fprintf(writer, "%s\n", fileName) fmt.Fprintf(writer, "%s\n", fileName)
err = reportWriter.WriteReport(writer) err = reportWriter.WriteReport(writer)
if err != nil { if err != nil {
return -1, fmt.Errorf("error while printing diff: %v", err) return -1, fmt.Errorf("error while printing diff: %w", err)
} }
} }
return len(report.Diffs), nil return len(report.Diffs), nil

View File

@ -135,7 +135,7 @@ func DefaultGetFiles(yamlFile string) ([]string, error) {
files = append(files, nodeFiles...) files = append(files, nodeFiles...)
} }
} else { } else {
return nil, fmt.Errorf("finding child files in failed: %v", err) return nil, fmt.Errorf("finding child files in failed: %w", err)
} }
} }

View File

@ -182,7 +182,7 @@ func SquashCmd(m *migrate.Migrate, from uint64, to int64, version int64, name, d
err = createOptions.Create() err = createOptions.Create()
if err != nil { if err != nil {
return versions, errors.Wrap(err, "cannot create migration") return versions, fmt.Errorf("cannot create migration: %w", err)
} }
return return

View File

@ -142,10 +142,10 @@ func NewHasuraError(data []byte, isCmd bool) error {
var herror HasuraError var herror HasuraError
err := json.Unmarshal(data, &herror) err := json.Unmarshal(data, &herror)
if err != nil { if err != nil {
return fmt.Errorf("failed parsing json: %v; response from API: %s", err, string(data)) return fmt.Errorf("failed parsing json: %w; response from API: %s", err, string(data))
} }
return herror return herror
default: default:
return fmt.Errorf("Data Error: %s", string(data)) return fmt.Errorf("Data Error: %s", string(data))
} }
} }

View File

@ -17,7 +17,6 @@ import (
migratedb "github.com/hasura/graphql-engine/cli/v2/migrate/database" migratedb "github.com/hasura/graphql-engine/cli/v2/migrate/database"
"github.com/hasura/graphql-engine/cli/v2" "github.com/hasura/graphql-engine/cli/v2"
"github.com/pkg/errors"
) )
// MultiError holds multiple errors. // MultiError holds multiple errors.
@ -166,7 +165,7 @@ func NewMigrate(ec *cli.ExecutionContext, isCmd bool, sourceName string, sourceK
t, err := New(opts) t, err := New(opts)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "cannot create migrate instance") return nil, fmt.Errorf("cannot create migrate instance: %w", err)
} }
if ec.Config.Version >= cli.V2 { if ec.Config.Version >= cli.V2 {
t.databaseDrv.EnableCheckMetadataConsistency(true) t.databaseDrv.EnableCheckMetadataConsistency(true)

View File

@ -10,7 +10,6 @@ import (
"testing" "testing"
"github.com/hasura/graphql-engine/cli/v2/internal/hasura" "github.com/hasura/graphql-engine/cli/v2/internal/hasura"
"github.com/hasura/graphql-engine/cli/v2/pkg/migrate" "github.com/hasura/graphql-engine/cli/v2/pkg/migrate"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -247,7 +246,7 @@ func TestProjectMetadata_Reload(t *testing.T) {
name string name string
fields fields fields fields
want string want string
wantErr bool wantErr require.ErrorAssertionFunc
}{ }{
{ {
"can reload metadata", "can reload metadata",
@ -256,21 +255,61 @@ func TestProjectMetadata_Reload(t *testing.T) {
endpointString: hgeEndpoint, endpointString: hgeEndpoint,
}, },
`{"message": "success"}`, `{"message": "success"}`,
false, require.NoError,
}, },
// TODO: automate the following tests
// following tests are currently ran manually by making use of https://github.com/Shopify/toxiproxy
//{
// "can return expected error type when graphql engine connections fail",
// fields{
// projectDirectory: "testdata/projectv3",
// endpointString: "http://localhost:12345/something",
// },
// `{"message": "success"}`,
// func(t require.TestingT, err error, i ...interface{}) {
// var e *url.Error
// require.Truef(t, errors.As(err, &e), "expected err to be an instance of %v but got %v", reflect.TypeOf(&url.Error{}), reflect.TypeOf(err))
// },
//},
// config.json
// [
// {
// "name": "hasura",
// "listen": "[::]:18080",
// "upstream": "localhost:8080",
// "enabled": true
// }
// ]
//
// 1. Simulate reset peer
// $ toxiproxy-cli toxic add -t reset_peer hasura
// 2. Simulate timeout
// $ toxiproxy-cli toxic add -t timeout -a timeout=1 hasura
//{
// "return expect error type when graphql engine connections reset",
// fields{
// projectDirectory: "testdata/projectv3",
// endpointString: "http://localhost:18080",
// },
// `{"message": "success"}`,
// func(t require.TestingT, err error, i ...interface{}) {
// var e *url.Error
// require.Truef(t, errors.As(err, &e), "expected err to be an instance of %v but got %v", reflect.TypeOf(&url.Error{}), reflect.TypeOf(err))
// },
//},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
p, err := NewProjectMetadata(tt.fields.projectDirectory, WithEndpoint(hgeEndpoint), WithAdminSecret(testutil.TestAdminSecret)) p, err := NewProjectMetadata(tt.fields.projectDirectory, WithEndpoint(tt.fields.endpointString), WithAdminSecret(testutil.TestAdminSecret))
require.NoError(t, err) tt.wantErr(t, err)
got, err := p.Reload() if p != nil {
if tt.wantErr { got, err := p.Reload()
require.Error(t, err)
tt.wantErr(t, err)
gotb, err := ioutil.ReadAll(got)
require.NoError(t, err)
require.JSONEq(t, tt.want, string(gotb))
} }
require.NoError(t, err)
gotb, err := ioutil.ReadAll(got)
require.NoError(t, err)
require.JSONEq(t, tt.want, string(gotb))
}) })
} }
} }

View File

@ -212,7 +212,17 @@ func TestProjectMigrate_Apply_Configv2(t *testing.T) {
require.Error(t, err) require.Error(t, err)
} else { } else {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tt.want, got) for idx, want := range tt.want {
if idx >= len(got) {
t.Errorf("expected to got to have equal number of elements: want %v got %v", len(tt.want), len(got))
}
if len(want.Message) > 0 {
assert.Equal(t, want.Message, got[idx].Message)
}
if want.Error != nil {
assert.Equal(t, want.Error.Error(), got[idx].Error.Error())
}
}
} }
}) })
} }

View File

@ -1,13 +1,15 @@
package util package util
import ( import (
"crypto/tls" "context"
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"net/url" "net/url"
"path" "path"
"github.com/parnurzeal/gorequest" "github.com/hasura/graphql-engine/cli/v2/internal/httpc"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -23,40 +25,42 @@ type hdbVersion struct {
} }
// GetServerState queries a server for the state. // GetServerState queries a server for the state.
func GetServerState(endpoint string, adminSecret string, config *tls.Config, hasMetadataV3 bool, log *logrus.Logger) *ServerState { func GetServerState(client *httpc.Client, endpoint string, hasMetadataV3 bool, log *logrus.Logger) *ServerState {
state := &ServerState{ state := &ServerState{
UUID: "00000000-0000-0000-0000-000000000000", UUID: "00000000-0000-0000-0000-000000000000",
} }
if hasMetadataV3 { if hasMetadataV3 {
payload := ` payload := []byte(`
{ {
"type": "get_catalog_state", "type": "get_catalog_state",
"args": {} "args": {}
} }
` `)
req := gorequest.New()
if config != nil {
req.TLSClientConfig(config)
}
req.Post(endpoint).Send(payload)
req.Set("X-Hasura-Admin-Secret", adminSecret)
var r struct { var r struct {
ID string `json:"id"` ID string `json:"id"`
} }
_, _, errs := req.EndStruct(&r) var body interface{}
if len(errs) != 0 { err := json.Unmarshal(payload, &body)
log.Debugf("server state: errors: %v", errs) if err != nil {
log.Debugf("unmarshalling json request to construct server state failed: %v", err)
return state
}
req, err := client.NewRequest(http.MethodPost, endpoint, body)
if err != nil {
log.Debugf("constructing http request to construct server state failed: %v", err)
return state
}
_, err = client.Do(context.Background(), req, &r)
if err != nil {
log.Debugf("http request to construct server state failed: %v", err)
return state return state
} }
state.UUID = r.ID state.UUID = r.ID
} else { } else {
state := &ServerState{ payload := []byte(`{
UUID: "00000000-0000-0000-0000-000000000000",
}
payload := `{
"type": "select", "type": "select",
"args": { "args": {
"table": { "table": {
@ -68,29 +72,28 @@ func GetServerState(endpoint string, adminSecret string, config *tls.Config, has
"cli_state" "cli_state"
] ]
} }
}` }`)
var body interface{}
req := gorequest.New() err := json.Unmarshal(payload, &body)
if config != nil { if err != nil {
req.TLSClientConfig(config) log.Debugf("unmarshalling json request to construct server state failed: %v", err)
return state
}
req, err := client.NewRequest(http.MethodPost, endpoint, body)
if err != nil {
log.Debugf("constructing http request to construct server state failed: %v", err)
return state
} }
req.Post(endpoint).Send(payload)
req.Set("X-Hasura-Admin-Secret", adminSecret)
var r []hdbVersion var r []hdbVersion
_, _, errs := req.EndStruct(&r) _, err = client.Do(context.Background(), req, &r)
if len(errs) != 0 { if err != nil {
log.Debugf("server state: errors: %v", errs) log.Debugf("http request to construct server state failed: %v", err)
return state return state
} }
if len(r) >= 1 {
if len(r) != 1 { state.UUID = r[0].UUID
log.Debugf("invalid response: %v", r) state.CLIState = r[0].CLIState
return state
} }
state.UUID = r[0].UUID
state.CLIState = r[0].CLIState
} }
return state return state
@ -104,7 +107,7 @@ func GetServerStatus(endpoint string) (err error) {
uri.Path = path.Join(uri.Path, "healthz") uri.Path = path.Join(uri.Path, "healthz")
resp, err := http.Get(uri.String()) resp, err := http.Get(uri.String())
if err != nil { if err != nil {
return fmt.Errorf("making http request failed: %s", err.Error()) return fmt.Errorf("making http request failed: %w", err)
} }
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
return fmt.Errorf("request failed: url: %s status code: %v status: %s", uri.String(), resp.StatusCode, resp.Status) return fmt.Errorf("request failed: url: %s status code: %v status: %s", uri.String(), resp.StatusCode, resp.Status)

58
cli/util/server_test.go Normal file
View File

@ -0,0 +1,58 @@
package util
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/hasura/graphql-engine/cli/v2/internal/httpc"
"github.com/hasura/graphql-engine/cli/v2/internal/testutil"
"github.com/sirupsen/logrus"
)
func TestGetServerState(t *testing.T) {
portV13, teardownV133 := testutil.StartHasura(t, "hasura/graphql-engine:v1.3.3")
hgeEndpointV133 := fmt.Sprintf("http://localhost:%s", portV13)
defer teardownV133()
port, teardown := testutil.StartHasura(t, testutil.HasuraDockerImage)
hgeEndpoint := fmt.Sprintf("http://localhost:%s", port)
defer teardown()
type args struct {
client *httpc.Client
endpoint string
hasMetadataV3 bool
log *logrus.Logger
}
tests := []struct {
name string
args args
}{
{
"can generate server state for v1.x",
args{
testutil.NewHttpcClient(t, portV13, nil),
fmt.Sprintf("%v/v1/query", hgeEndpointV133),
false,
logrus.New(),
},
},
{
"can generate server state for latest",
args{
testutil.NewHttpcClient(t, port, nil),
fmt.Sprintf("%v/v1/metadata", hgeEndpoint),
true,
logrus.New(),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := GetServerState(tt.args.client, tt.args.endpoint, tt.args.hasMetadataV3, tt.args.log)
assert.Truef(t, got.UUID != "00000000-0000-0000-0000-000000000000" && got.UUID != "", "expected server UUID to be set got: ", got.UUID)
})
}
}