Skip to content

Commit 21b61af

Browse files
authored
cli: allow customization of server api paths (close hasura#4016) (hasura#4174)
1 parent b02cd33 commit 21b61af

File tree

6 files changed

+94
-28
lines changed

6 files changed

+94
-28
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ The order and collapsed state of columns is now persisted across page navigation
1111

1212
### Bug fixes and improvements
1313

14+
- cli: allow customization of server api paths (close #4016)
1415
- cli: clean up migration files created during a failed migrate api (close #4312) (#4319)
1516
- cli: add support for multiple versions of plugin (close #4105)
1617
- cli: template assets path in console HTML for unversioned builds

cli/cli.go

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ import (
1212
"io/ioutil"
1313
"net/url"
1414
"os"
15+
"path"
1516
"path/filepath"
17+
"reflect"
1618
"strconv"
1719
"strings"
1820
"time"
@@ -61,6 +63,36 @@ const (
6163
V2
6264
)
6365

66+
// ServerAPIPaths has the custom paths defined for server api
67+
type ServerAPIPaths struct {
68+
Query string `yaml:"query,omitempty"`
69+
GraphQL string `yaml:"graphql,omitempty"`
70+
Config string `yaml:"config,omitempty"`
71+
PGDump string `yaml:"pg_dump,omitempty"`
72+
Version string `yaml:"version,omitempty"`
73+
}
74+
75+
// GetQueryParams - encodes the values in url
76+
func (s ServerAPIPaths) GetQueryParams() url.Values {
77+
vals := url.Values{}
78+
t := reflect.TypeOf(s)
79+
for i := 0; i < t.NumField(); i++ {
80+
field := t.Field(i)
81+
tag := field.Tag.Get("yaml")
82+
splitTag := strings.Split(tag, ",")
83+
if len(splitTag) == 0 {
84+
continue
85+
}
86+
name := splitTag[0]
87+
if name == "-" {
88+
continue
89+
}
90+
v := reflect.ValueOf(s).Field(i)
91+
vals.Add(name, v.String())
92+
}
93+
return vals
94+
}
95+
6496
// ErrInvalidConfigVersion - if the config version is not valid
6597
var ErrInvalidConfigVersion error = fmt.Errorf("invalid config version")
6698

@@ -105,10 +137,19 @@ type ServerConfig struct {
105137
AccessKey string `yaml:"access_key,omitempty"`
106138
// AdminSecret (optional) Admin secret required to query the endpoint
107139
AdminSecret string `yaml:"admin_secret,omitempty"`
140+
// APIPaths (optional) API paths for server
141+
APIPaths *ServerAPIPaths `yaml:"api_paths,omitempty"`
108142

109143
ParsedEndpoint *url.URL `yaml:"-"`
110144
}
111145

146+
// GetVersionEndpoint provides the url to contact the version API
147+
func (s *ServerConfig) GetVersionEndpoint() string {
148+
nurl := *s.ParsedEndpoint
149+
nurl.Path = path.Join(nurl.Path, s.APIPaths.Version)
150+
return nurl.String()
151+
}
152+
112153
// ParseEndpoint ensures the endpoint is valid.
113154
func (s *ServerConfig) ParseEndpoint() error {
114155
nurl, err := url.Parse(s.Endpoint)
@@ -398,7 +439,7 @@ func (ec *ExecutionContext) Validate() error {
398439
}
399440

400441
func (ec *ExecutionContext) checkServerVersion() error {
401-
v, err := version.FetchServerVersion(ec.Config.ServerConfig.Endpoint)
442+
v, err := version.FetchServerVersion(ec.Config.ServerConfig.GetVersionEndpoint())
402443
if err != nil {
403444
return errors.Wrap(err, "failed to get version from server")
404445
}
@@ -441,6 +482,11 @@ func (ec *ExecutionContext) readConfig() error {
441482
v.SetDefault("endpoint", "http://localhost:8080")
442483
v.SetDefault("admin_secret", "")
443484
v.SetDefault("access_key", "")
485+
v.SetDefault("api_paths.query", "v1/query")
486+
v.SetDefault("api_paths.graphql", "v1/graphql")
487+
v.SetDefault("api_paths.config", "v1alpha1/config")
488+
v.SetDefault("api_paths.pg_dump", "v1alpha1/pg_dump")
489+
v.SetDefault("api_paths.version", "v1/version")
444490
v.SetDefault("metadata_directory", "")
445491
v.SetDefault("migrations_directory", "migrations")
446492
v.SetDefault("actions.kind", "synchronous")
@@ -462,6 +508,13 @@ func (ec *ExecutionContext) readConfig() error {
462508
ServerConfig: ServerConfig{
463509
Endpoint: v.GetString("endpoint"),
464510
AdminSecret: adminSecret,
511+
APIPaths: &ServerAPIPaths{
512+
Query: v.GetString("api_paths.query"),
513+
GraphQL: v.GetString("api_paths.graphql"),
514+
Config: v.GetString("api_paths.config"),
515+
PGDump: v.GetString("api_paths.pg_dump"),
516+
Version: v.GetString("api_paths.version"),
517+
},
465518
},
466519
MetadataDirectory: v.GetString("metadata_directory"),
467520
MigrationsDirectory: v.GetString("migrations_directory"),

cli/commands/scripts_update_config_v2.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"gopkg.in/yaml.v2"
1313

1414
"github.com/hasura/graphql-engine/cli"
15+
"github.com/hasura/graphql-engine/cli/metadata/actions/types"
1516
"github.com/hasura/graphql-engine/cli/migrate/database/hasuradb"
1617
"github.com/hasura/graphql-engine/cli/migrate/source"
1718
"github.com/hasura/graphql-engine/cli/migrate/source/file"
@@ -319,7 +320,23 @@ func newScriptsUpdateConfigV2Cmd(ec *cli.ExecutionContext) *cobra.Command {
319320
return errors.Wrap(err, "cannot write metadata")
320321
}
321322
ec.Spin("Writing new config file...")
322-
err = ec.WriteConfig(nil)
323+
// Read the config from config.yaml
324+
cfgByt, err := ioutil.ReadFile(ec.ConfigFile)
325+
if err != nil {
326+
return errors.Wrap(err, "cannot read config file")
327+
}
328+
var cfg cli.Config
329+
err = yaml.Unmarshal(cfgByt, &cfg)
330+
if err != nil {
331+
return errors.Wrap(err, "cannot parse config file")
332+
}
333+
cfg.Version = cli.V2
334+
cfg.MetadataDirectory = ec.Viper.GetString("metadata_directory")
335+
cfg.ActionConfig = &types.ActionExecutionConfig{
336+
Kind: ec.Viper.GetString("actions.kind"),
337+
HandlerWebhookBaseURL: ec.Viper.GetString("actions.handler_webhook_baseurl"),
338+
}
339+
err = ec.WriteConfig(&cfg)
323340
if err != nil {
324341
return errors.Wrap(err, "cannot write config file")
325342
}

cli/migrate/database/hasuradb/hasuradb.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ var (
4040
type Config struct {
4141
MigrationsTable string
4242
SettingsTable string
43-
v1URL *nurl.URL
43+
queryURL *nurl.URL
4444
graphqlURL *nurl.URL
45-
schemDumpURL *nurl.URL
45+
pgDumpURL *nurl.URL
4646
Headers map[string]string
4747
isCMD bool
4848
Plugins types.MetadataPlugins
@@ -115,20 +115,20 @@ func (h *HasuraDB) Open(url string, isCMD bool, logger *log.Logger) (database.Dr
115115
config := &Config{
116116
MigrationsTable: DefaultMigrationsTable,
117117
SettingsTable: DefaultSettingsTable,
118-
v1URL: &nurl.URL{
118+
queryURL: &nurl.URL{
119119
Scheme: scheme,
120120
Host: hurl.Host,
121-
Path: path.Join(hurl.Path, "v1/query"),
121+
Path: path.Join(hurl.Path, params.Get("query")),
122122
},
123123
graphqlURL: &nurl.URL{
124124
Scheme: scheme,
125125
Host: hurl.Host,
126-
Path: path.Join(hurl.Path, "v1/graphql"),
126+
Path: path.Join(hurl.Path, params.Get("graphql")),
127127
},
128-
schemDumpURL: &nurl.URL{
128+
pgDumpURL: &nurl.URL{
129129
Scheme: scheme,
130130
Host: hurl.Host,
131-
Path: path.Join(hurl.Path, "v1alpha1/pg_dump"),
131+
Path: path.Join(hurl.Path, params.Get("pg_dump")),
132132
},
133133
isCMD: isCMD,
134134
Headers: headers,
@@ -417,7 +417,7 @@ func (h *HasuraDB) ensureVersionTable() error {
417417

418418
func (h *HasuraDB) sendv1Query(m interface{}) (resp *http.Response, body []byte, err error) {
419419
request := gorequest.New()
420-
request = request.Post(h.config.v1URL.String()).Send(m)
420+
request = request.Post(h.config.queryURL.String()).Send(m)
421421
for headerName, headerValue := range h.config.Headers {
422422
request.Set(headerName, headerValue)
423423
}
@@ -455,7 +455,7 @@ func (h *HasuraDB) sendv1GraphQL(query interface{}) (resp *http.Response, body [
455455
func (h *HasuraDB) sendSchemaDumpQuery(m interface{}) (resp *http.Response, body []byte, err error) {
456456
request := gorequest.New()
457457

458-
request = request.Post(h.config.schemDumpURL.String()).Send(m)
458+
request = request.Post(h.config.pgDumpURL.String()).Send(m)
459459

460460
for headerName, headerValue := range h.config.Headers {
461461
request.Set(headerName, headerValue)

cli/migrate/util.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ func FilterCustomQuery(u *nurl.URL) *nurl.URL {
121121
}
122122

123123
func NewMigrate(ec *cli.ExecutionContext, isCmd bool) (*Migrate, error) {
124-
dbURL := GetDataPath(ec.Config.ServerConfig.ParsedEndpoint, GetAdminSecretHeaderName(ec.Version), ec.Config.ServerConfig.AdminSecret)
124+
dbURL := GetDataPath(ec)
125125
fileURL := GetFilePath(ec.MigrationDir)
126126
t, err := New(fileURL.String(), dbURL.String(), isCmd, int(ec.Config.Version), ec.Logger)
127127
if err != nil {
@@ -132,22 +132,24 @@ func NewMigrate(ec *cli.ExecutionContext, isCmd bool) (*Migrate, error) {
132132
return t, nil
133133
}
134134

135-
func GetDataPath(url *nurl.URL, adminSecretHeader, adminSecretValue string) *nurl.URL {
135+
func GetDataPath(ec *cli.ExecutionContext) *nurl.URL {
136+
url := ec.Config.ServerConfig.ParsedEndpoint
136137
host := &nurl.URL{
137-
Scheme: "hasuradb",
138-
Host: url.Host,
139-
Path: url.Path,
138+
Scheme: "hasuradb",
139+
Host: url.Host,
140+
Path: url.Path,
141+
RawQuery: ec.Config.ServerConfig.APIPaths.GetQueryParams().Encode(),
140142
}
141-
q := url.Query()
143+
q := host.Query()
142144
// Set sslmode in query
143145
switch scheme := url.Scheme; scheme {
144146
case "https":
145147
q.Set("sslmode", "enable")
146148
default:
147149
q.Set("sslmode", "disable")
148150
}
149-
if adminSecretValue != "" {
150-
q.Add("headers", fmt.Sprintf("%s:%s", adminSecretHeader, adminSecretValue))
151+
if GetAdminSecretHeaderName(ec.Version) != "" {
152+
q.Add("headers", fmt.Sprintf("%s:%s", GetAdminSecretHeaderName(ec.Version), ec.Config.ServerConfig.AdminSecret))
151153
}
152154
host.RawQuery = q.Encode()
153155
return host

cli/version/server.go

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
package version
22

33
import (
4-
"fmt"
54
"io/ioutil"
65
"net/http"
7-
"net/url"
86

97
yaml "github.com/ghodss/yaml"
108
"github.com/pkg/errors"
@@ -16,12 +14,7 @@ type serverVersionResponse struct {
1614

1715
// FetchServerVersion reads the version from server.
1816
func FetchServerVersion(endpoint string) (version string, err error) {
19-
ep, err := url.Parse(endpoint)
20-
if err != nil {
21-
return "", errors.Wrap(err, "cannot parse endpoint as a valid url")
22-
}
23-
versionEndpoint := fmt.Sprintf("%s/v1/version", ep.String())
24-
response, err := http.Get(versionEndpoint)
17+
response, err := http.Get(endpoint)
2518
if err != nil {
2619
return "", errors.Wrap(err, "failed making version api call")
2720
}
@@ -30,7 +23,7 @@ func FetchServerVersion(endpoint string) (version string, err error) {
3023
case http.StatusNotFound:
3124
return "", nil
3225
default:
33-
return "", errors.Errorf("GET %s failed - [%d]", versionEndpoint, response.StatusCode)
26+
return "", errors.Errorf("GET %s failed - [%d]", endpoint, response.StatusCode)
3427
}
3528
} else {
3629
defer response.Body.Close()

0 commit comments

Comments
 (0)