summaryrefslogtreecommitdiff
path: root/data
diff options
context:
space:
mode:
authorDave Henderson <dhenderson@gmail.com>2020-05-20 22:56:01 -0400
committerDave Henderson <dhenderson@gmail.com>2020-05-20 22:56:01 -0400
commitaa527c49e11a5c158cf87df9969b882395a735e7 (patch)
tree41d040e7ef706b1160bcf6297e0f69b9b3078d2c /data
parent7597dd94a53f834e67c35df51dccf90fe56b7f82 (diff)
Refactoring: deduplicating identical URL-parsing functions
Signed-off-by: Dave Henderson <dhenderson@gmail.com>
Diffstat (limited to 'data')
-rw-r--r--data/datasource.go109
-rw-r--r--data/datasource_http.go38
-rw-r--r--data/datasource_http_test.go44
-rw-r--r--data/datasource_merge.go7
-rw-r--r--data/datasource_test.go115
5 files changed, 11 insertions, 302 deletions
diff --git a/data/datasource.go b/data/datasource.go
index 456b5a12..04cf6c8a 100644
--- a/data/datasource.go
+++ b/data/datasource.go
@@ -8,7 +8,6 @@ import (
"net/http"
"net/url"
"os"
- "path"
"path/filepath"
"strings"
@@ -101,28 +100,14 @@ func (d *Data) Cleanup() {
}
// NewData - constructor for Data
+// Deprecated: will be replaced in future
func NewData(datasourceArgs, headerArgs []string) (*Data, error) {
- headers, err := parseHeaderArgs(headerArgs)
+ cfg := &config.Config{}
+ err := cfg.ParseDataSourceFlags(datasourceArgs, nil, headerArgs)
if err != nil {
return nil, err
}
-
- data := &Data{
- Sources: make(map[string]*Source),
- extraHeaders: headers,
- }
-
- for _, v := range datasourceArgs {
- s, err := parseSource(v)
- if err != nil {
- return nil, errors.Wrapf(err, "error parsing datasource")
- }
- s.header = headers[s.Alias]
- // pop the header out of the map, so we end up with only the unreferenced ones
- delete(headers, s.Alias)
-
- data.Sources[s.Alias] = s
- }
+ data := FromConfig(cfg)
return data, nil
}
@@ -242,90 +227,6 @@ func (s *Source) String() string {
return fmt.Sprintf("%s=%s (%s)", s.Alias, s.URL.String(), s.mediaType)
}
-// parseSource creates a *Source by parsing the value provided to the
-// --datasource/-d commandline flag
-func parseSource(value string) (source *Source, err error) {
- source = &Source{}
- parts := strings.SplitN(value, "=", 2)
- if len(parts) == 1 {
- f := parts[0]
- source.Alias = strings.SplitN(value, ".", 2)[0]
- if path.Base(f) != f {
- err = errors.Errorf("Invalid datasource (%s). Must provide an alias with files not in working directory", value)
- return nil, err
- }
- source.URL, err = absFileURL(f)
- if err != nil {
- return nil, err
- }
- } else if len(parts) == 2 {
- source.Alias = parts[0]
- source.URL, err = parseSourceURL(parts[1])
- if err != nil {
- return nil, err
- }
- }
-
- return source, nil
-}
-
-func parseSourceURL(value string) (*url.URL, error) {
- if value == "-" {
- value = "stdin://"
- }
- value = filepath.ToSlash(value)
- // handle absolute Windows paths
- volName := ""
- if volName = filepath.VolumeName(value); volName != "" {
- // handle UNCs
- if len(volName) > 2 {
- value = "file:" + value
- } else {
- value = "file:///" + value
- }
- }
- srcURL, err := url.Parse(value)
- if err != nil {
- return nil, err
- }
-
- if volName != "" {
- if strings.HasPrefix(srcURL.Path, "/") && srcURL.Path[2] == ':' {
- srcURL.Path = srcURL.Path[1:]
- }
- }
-
- if !srcURL.IsAbs() {
- srcURL, err = absFileURL(value)
- if err != nil {
- return nil, err
- }
- }
- return srcURL, nil
-}
-
-func absFileURL(value string) (*url.URL, error) {
- cwd, err := os.Getwd()
- if err != nil {
- return nil, errors.Wrapf(err, "can't get working directory")
- }
- urlCwd := filepath.ToSlash(cwd)
- baseURL := &url.URL{
- Scheme: "file",
- Path: urlCwd + "/",
- }
- relURL, err := url.Parse(value)
- if err != nil {
- return nil, fmt.Errorf("can't parse value %s as URL: %w", value, err)
- }
- resolved := baseURL.ResolveReference(relURL)
- // deal with Windows drive letters
- if !strings.HasPrefix(urlCwd, "/") && resolved.Path[2] == ':' {
- resolved.Path = resolved.Path[1:]
- }
- return resolved, nil
-}
-
// DefineDatasource -
func (d *Data) DefineDatasource(alias, value string) (string, error) {
if alias == "" {
@@ -334,7 +235,7 @@ func (d *Data) DefineDatasource(alias, value string) (string, error) {
if d.DatasourceExists(alias) {
return "", nil
}
- srcURL, err := parseSourceURL(value)
+ srcURL, err := config.ParseSourceURL(value)
if err != nil {
return "", err
}
diff --git a/data/datasource_http.go b/data/datasource_http.go
index 5424fbd0..e809768e 100644
--- a/data/datasource_http.go
+++ b/data/datasource_http.go
@@ -5,7 +5,6 @@ import (
"mime"
"net/http"
"net/url"
- "strings"
"time"
"github.com/pkg/errors"
@@ -61,40 +60,3 @@ func readHTTP(source *Source, args ...string) ([]byte, error) {
}
return body, nil
}
-
-func parseHeaderArgs(headerArgs []string) (map[string]http.Header, error) {
- headers := make(map[string]http.Header)
- for _, v := range headerArgs {
- ds, name, value, err := splitHeaderArg(v)
- if err != nil {
- return nil, err
- }
- if _, ok := headers[ds]; !ok {
- headers[ds] = make(http.Header)
- }
- headers[ds][name] = append(headers[ds][name], strings.TrimSpace(value))
- }
- return headers, nil
-}
-
-func splitHeaderArg(arg string) (datasourceAlias, name, value string, err error) {
- parts := strings.SplitN(arg, "=", 2)
- if len(parts) != 2 {
- err = errors.Errorf("Invalid datasource-header option '%s'", arg)
- return "", "", "", err
- }
- datasourceAlias = parts[0]
- name, value, err = splitHeader(parts[1])
- return datasourceAlias, name, value, err
-}
-
-func splitHeader(header string) (name, value string, err error) {
- parts := strings.SplitN(header, ":", 2)
- if len(parts) != 2 {
- err = errors.Errorf("Invalid HTTP Header format '%s'", header)
- return "", "", err
- }
- name = http.CanonicalHeaderKey(parts[0])
- value = parts[1]
- return name, value, nil
-}
diff --git a/data/datasource_http_test.go b/data/datasource_http_test.go
index f35733db..7f8515cc 100644
--- a/data/datasource_http_test.go
+++ b/data/datasource_http_test.go
@@ -118,50 +118,6 @@ func TestHTTPFileWithHeaders(t *testing.T) {
assert.Equal(t, must(marshalObj(expected, json.Marshal)), must(marshalObj(actual, json.Marshal)))
}
-func TestParseHeaderArgs(t *testing.T) {
- args := []string{
- "foo=Accept: application/json",
- "bar=Authorization: Bearer supersecret",
- }
- expected := map[string]http.Header{
- "foo": {
- "Accept": {jsonMimetype},
- },
- "bar": {
- "Authorization": {"Bearer supersecret"},
- },
- }
- parsed, err := parseHeaderArgs(args)
- assert.NoError(t, err)
- assert.Equal(t, expected, parsed)
-
- _, err = parseHeaderArgs([]string{"foo"})
- assert.Error(t, err)
-
- _, err = parseHeaderArgs([]string{"foo=bar"})
- assert.Error(t, err)
-
- args = []string{
- "foo=Accept: application/json",
- "foo=Foo: bar",
- "foo=foo: baz",
- "foo=fOO: qux",
- "bar=Authorization: Bearer supersecret",
- }
- expected = map[string]http.Header{
- "foo": {
- "Accept": {jsonMimetype},
- "Foo": {"bar", "baz", "qux"},
- },
- "bar": {
- "Authorization": {"Bearer supersecret"},
- },
- }
- parsed, err = parseHeaderArgs(args)
- assert.NoError(t, err)
- assert.Equal(t, expected, parsed)
-}
-
func TestBuildURL(t *testing.T) {
expected := "https://example.com/index.html"
base := mustParseURL(expected)
diff --git a/data/datasource_merge.go b/data/datasource_merge.go
index da14f24d..fa69c81f 100644
--- a/data/datasource_merge.go
+++ b/data/datasource_merge.go
@@ -4,6 +4,7 @@ import (
"strings"
"github.com/hairyhenderson/gomplate/v3/coll"
+ "github.com/hairyhenderson/gomplate/v3/internal/config"
"github.com/pkg/errors"
)
@@ -30,10 +31,14 @@ func (d *Data) readMerge(source *Source, args ...string) ([]byte, error) {
subSource, err := d.lookupSource(part)
if err != nil {
// maybe it's a relative filename?
- subSource, err = parseSource(part + "=" + part)
+ u, err := config.ParseSourceURL(part)
if err != nil {
return nil, err
}
+ subSource = &Source{
+ Alias: part,
+ URL: u,
+ }
}
subSource.inherit(source)
diff --git a/data/datasource_test.go b/data/datasource_test.go
index 6752d9e5..62e1770e 100644
--- a/data/datasource_test.go
+++ b/data/datasource_test.go
@@ -4,8 +4,6 @@ import (
"fmt"
"net/http"
"net/url"
- "os"
- "path/filepath"
"runtime"
"strings"
"testing"
@@ -43,74 +41,6 @@ func TestNewData(t *testing.T) {
assert.Equal(t, "blah", d.Sources["foo"].header["Accept"][0])
}
-func TestParseSourceNoAlias(t *testing.T) {
- s, err := parseSource("foo.json")
- assert.NoError(t, err)
- assert.Equal(t, "foo", s.Alias)
-
- _, err = parseSource("../foo.json")
- assert.Error(t, err)
-
- _, err = parseSource("ftp://example.com/foo.yml")
- assert.Error(t, err)
-}
-
-func TestParseSourceWithAlias(t *testing.T) {
- s, err := parseSource("data=foo.json")
- assert.NoError(t, err)
- assert.Equal(t, "data", s.Alias)
- assert.Equal(t, "file", s.URL.Scheme)
- assert.True(t, s.URL.IsAbs())
-
- s, err = parseSource("data=/otherdir/foo.json")
- assert.NoError(t, err)
- assert.Equal(t, "data", s.Alias)
- assert.Equal(t, "file", s.URL.Scheme)
- assert.True(t, s.URL.IsAbs())
- assert.Equal(t, "/otherdir/foo.json", s.URL.Path)
-
- if runtime.GOOS == osWindows {
- s, err = parseSource("data=foo.json")
- assert.NoError(t, err)
- assert.Equalf(t, byte(':'), s.URL.Path[1], "Path was %s", s.URL.Path)
-
- s, err = parseSource(`data=\otherdir\foo.json`)
- assert.NoError(t, err)
- assert.Equal(t, "data", s.Alias)
- assert.Equal(t, "file", s.URL.Scheme)
- assert.True(t, s.URL.IsAbs())
- assert.Equal(t, `/otherdir/foo.json`, s.URL.Path)
-
- s, err = parseSource("data=C:\\windowsdir\\foo.json")
- assert.NoError(t, err)
- assert.Equal(t, "data", s.Alias)
- assert.Equal(t, "file", s.URL.Scheme)
- assert.True(t, s.URL.IsAbs())
- assert.Equal(t, "C:/windowsdir/foo.json", s.URL.Path)
-
- s, err = parseSource("data=\\\\somehost\\share\\foo.json")
- assert.NoError(t, err)
- assert.Equal(t, "data", s.Alias)
- assert.Equal(t, "file", s.URL.Scheme)
- assert.Equal(t, "somehost", s.URL.Host)
- assert.True(t, s.URL.IsAbs())
- assert.Equal(t, "/share/foo.json", s.URL.Path)
- }
-
- s, err = parseSource("data=sftp://example.com/blahblah/foo.json")
- assert.NoError(t, err)
- assert.Equal(t, "data", s.Alias)
- assert.Equal(t, "sftp", s.URL.Scheme)
- assert.True(t, s.URL.IsAbs())
- assert.Equal(t, "/blahblah/foo.json", s.URL.Path)
-
- s, err = parseSource("merged=merge:./foo.yaml|http://example.com/bar.json%3Ffoo=bar")
- assert.NoError(t, err)
- assert.Equal(t, "merged", s.Alias)
- assert.Equal(t, "merge", s.URL.Scheme)
- assert.Equal(t, "./foo.yaml|http://example.com/bar.json%3Ffoo=bar", s.URL.Opaque)
-}
-
func TestDatasource(t *testing.T) {
setup := func(ext, mime string, contents []byte) *Data {
fname := "foo." + ext
@@ -413,51 +343,6 @@ func TestMimeTypeWithArg(t *testing.T) {
}
}
-func TestQueryParse(t *testing.T) {
- expected := &url.URL{
- Scheme: "http",
- Host: "example.com",
- Path: "/foo.json",
- RawQuery: "bar",
- }
- u, err := parseSourceURL("http://example.com/foo.json?bar")
- assert.NoError(t, err)
- assert.EqualValues(t, expected, u)
-}
-
-func TestAbsFileURL(t *testing.T) {
- cwd, _ := os.Getwd()
- // make this pass on Windows
- cwd = filepath.ToSlash(cwd)
- expected := &url.URL{
- Scheme: "file",
- Host: "",
- Path: "/tmp/foo",
- }
- u, err := absFileURL("/tmp/foo")
- assert.NoError(t, err)
- assert.EqualValues(t, expected, u)
-
- expected = &url.URL{
- Scheme: "file",
- Host: "",
- Path: cwd + "/tmp/foo",
- }
- u, err = absFileURL("tmp/foo")
- assert.NoError(t, err)
- assert.EqualValues(t, expected, u)
-
- expected = &url.URL{
- Scheme: "file",
- Host: "",
- Path: cwd + "/tmp/foo",
- RawQuery: "q=p",
- }
- u, err = absFileURL("tmp/foo?q=p")
- assert.NoError(t, err)
- assert.EqualValues(t, expected, u)
-}
-
func TestFromConfig(t *testing.T) {
cfg := &config.Config{}
expected := &Data{