mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-09-18 13:22:17 +00:00
Refactor parseHostSpec
Fix ssh parsing in issue 4847
This commit is contained in:
@@ -228,46 +228,90 @@ func parsePath(n string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseHostSpec(n string) (string, string) {
|
func parseHostSpec(n string) (string, string) {
|
||||||
var host string
|
// We used to use go-getter to handle our urls: https://github.com/hashicorp/go-getter.
|
||||||
// Start accumulating the host part.
|
// This prefix signaled go-getter to use the git protocol to fetch the url's contents.
|
||||||
for _, p := range []string{
|
// We still accept this prefix.
|
||||||
// Order matters here.
|
n, _ = trimPrefixIgnoreCase(n, "git::")
|
||||||
"git::", "gh:", "ssh://", "https://", "http://", "file://",
|
// We support gh: assuming authors use it as a github shorthand, specified in .gitconfig.
|
||||||
"git@", "github.com:", "github.com/"} {
|
if rest, found := trimPrefixIgnoreCase(n, "gh:"); found {
|
||||||
if len(p) < len(n) && strings.ToLower(n[:len(p)]) == p {
|
return "gh:", rest
|
||||||
n = n[len(p):]
|
|
||||||
host += p
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if host == "git@" {
|
scheme, rest, _ := strings.Cut(n, "://")
|
||||||
i := strings.Index(n, "/")
|
switch scheme = strings.ToLower(scheme); scheme {
|
||||||
if i > -1 {
|
// no scheme
|
||||||
host += n[:i+1]
|
case strings.ToLower(n):
|
||||||
n = n[i+1:]
|
scheme = ""
|
||||||
|
rest = n
|
||||||
|
// The file protocol specifies an absolute path to a local git repo. There is no host.
|
||||||
|
case "file":
|
||||||
|
return "file://", rest
|
||||||
|
case "https", "http", "ssh":
|
||||||
|
scheme += "://"
|
||||||
|
// We either
|
||||||
|
// 1. do not support said scheme or
|
||||||
|
// 2. found a part of the path because there is no scheme.
|
||||||
|
// Instead of determining the case, we try to match the host as if under the 2nd case.
|
||||||
|
// If we are actually under the first, host matching will fail.
|
||||||
|
default:
|
||||||
|
scheme = ""
|
||||||
|
rest = n
|
||||||
|
}
|
||||||
|
return matchHost(scheme, rest)
|
||||||
|
}
|
||||||
|
|
||||||
|
// trimPrefixIgnoreCase returns the rest of s and true if prefix, ignoring case, prefixes s.
|
||||||
|
// Otherwise, trimPrefixIgnoreCase returns s and false.
|
||||||
|
func trimPrefixIgnoreCase(s, prefix string) (string, bool) {
|
||||||
|
if len(prefix) <= len(s) && strings.ToLower(s[:len(prefix)]) == prefix {
|
||||||
|
return s[len(prefix):], true
|
||||||
|
}
|
||||||
|
return s, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// matchHost returns a host that kustomize recognizes and the rest of s given scheme and url s.
|
||||||
|
// scheme can be any of http;//, https://, ssh://, or empty.
|
||||||
|
func matchHost(scheme, s string) (host, rest string) {
|
||||||
|
var isSCP bool
|
||||||
|
if s, isSCP = trimPrefixIgnoreCase(s, "git@"); isSCP {
|
||||||
|
host = "git@"
|
||||||
|
}
|
||||||
|
const httpGithub = "https://github.com/"
|
||||||
|
const scpGithub = "git@github.com:"
|
||||||
|
var normalized, separator string
|
||||||
|
switch scheme {
|
||||||
|
case "":
|
||||||
|
if isSCP {
|
||||||
|
normalized = scpGithub
|
||||||
|
separator = ":"
|
||||||
} else {
|
} else {
|
||||||
i = strings.Index(n, ":")
|
normalized = httpGithub
|
||||||
if i > -1 {
|
|
||||||
host += n[:i+1]
|
|
||||||
n = n[i+1:]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return host, n
|
case "https://", "http://":
|
||||||
|
normalized = httpGithub
|
||||||
|
separator = "/"
|
||||||
|
case "ssh://":
|
||||||
|
normalized = scpGithub
|
||||||
|
separator = "/"
|
||||||
}
|
}
|
||||||
|
for _, builtin := range []string{"github.com:", "github.com/"} {
|
||||||
// If host is a http(s) or ssh URL, grab the domain part.
|
rest, found := trimPrefixIgnoreCase(s, builtin)
|
||||||
for _, p := range []string{
|
if found {
|
||||||
"ssh://", "https://", "http://"} {
|
return normalized, rest
|
||||||
if strings.HasSuffix(host, p) {
|
|
||||||
i := strings.Index(n, "/")
|
|
||||||
if i > -1 {
|
|
||||||
host += n[0 : i+1]
|
|
||||||
n = n[i+1:]
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
i := strings.Index(s, separator)
|
||||||
return normalizeGitHostSpec(host), n
|
// There is no host if the separator was not found or the separator delimits an empty
|
||||||
|
// host. Note that this will happen if the separator is empty.
|
||||||
|
if i <= 0 {
|
||||||
|
return "", s
|
||||||
|
}
|
||||||
|
if separator == ":" {
|
||||||
|
// The colon acts as a delimiter for scp protocol only if not prefixed by '/'.
|
||||||
|
if slashIndex := strings.Index(s, "/"); slashIndex != -1 && slashIndex < i {
|
||||||
|
return "", s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return scheme + host + s[:i+1], s[i+1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalizeGitHostSpec(host string) string {
|
func normalizeGitHostSpec(host string) string {
|
||||||
|
|||||||
@@ -89,6 +89,10 @@ func TestNewRepoSpecFromUrlErrors(t *testing.T) {
|
|||||||
"htxxxtp://github.com/",
|
"htxxxtp://github.com/",
|
||||||
"url lacks host",
|
"url lacks host",
|
||||||
},
|
},
|
||||||
|
"bad_scp": {
|
||||||
|
"git@local/path:file/system",
|
||||||
|
"url lacks host",
|
||||||
|
},
|
||||||
"no_org_repo": {
|
"no_org_repo": {
|
||||||
"ssh://git.example.com",
|
"ssh://git.example.com",
|
||||||
"url lacks repoPath",
|
"url lacks repoPath",
|
||||||
@@ -191,27 +195,40 @@ func TestNewRepoSpecFromUrl_Smoke(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "t6",
|
name: "t6",
|
||||||
input: "git@gitlab2.sqtools.ru:10022/infra/kubernetes/thanos-base.git?ref=v0.1.0",
|
input: "git@gitlab2.sqtools.ru:infra/kubernetes/thanos-base.git?ref=v0.1.0",
|
||||||
cloneSpec: "git@gitlab2.sqtools.ru:10022/infra/kubernetes/thanos-base.git",
|
cloneSpec: "git@gitlab2.sqtools.ru:infra/kubernetes/thanos-base.git",
|
||||||
absPath: notCloned.String(),
|
absPath: notCloned.String(),
|
||||||
repoSpec: RepoSpec{
|
repoSpec: RepoSpec{
|
||||||
Host: "git@gitlab2.sqtools.ru:10022/",
|
Host: "git@gitlab2.sqtools.ru:",
|
||||||
RepoPath: "infra/kubernetes/thanos-base",
|
RepoPath: "infra/kubernetes/thanos-base",
|
||||||
Ref: "v0.1.0",
|
Ref: "v0.1.0",
|
||||||
GitSuffix: ".git",
|
GitSuffix: ".git",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "t7",
|
name: "non-github_scp",
|
||||||
input: "git@bitbucket.org:company/project.git//path?ref=branch",
|
input: "git@bitbucket.org:company/project.git//path?ref=branch",
|
||||||
cloneSpec: "git@bitbucket.org:company/project.git",
|
cloneSpec: "git@bitbucket.org:company/project.git",
|
||||||
absPath: notCloned.Join("path"),
|
absPath: notCloned.Join("path"),
|
||||||
repoSpec: RepoSpec{
|
repoSpec: RepoSpec{
|
||||||
Host: "git@bitbucket.org:company/",
|
Host: "git@bitbucket.org:",
|
||||||
RepoPath: "project",
|
RepoPath: "company/project",
|
||||||
KustRootPath: "/path",
|
KustRootPath: "/path",
|
||||||
Ref: "branch",
|
Ref: "branch",
|
||||||
GitSuffix: ".git",
|
GitSuffix: ".git",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-github_git-user_ssh",
|
||||||
|
input: "ssh://git@bitbucket.org/company/project.git//path?ref=branch",
|
||||||
|
cloneSpec: "ssh://git@bitbucket.org/company/project.git",
|
||||||
|
absPath: notCloned.Join("path"),
|
||||||
|
repoSpec: RepoSpec{
|
||||||
|
Host: "ssh://git@bitbucket.org/",
|
||||||
|
RepoPath: "company/project",
|
||||||
|
KustRootPath: "/path",
|
||||||
|
Ref: "branch",
|
||||||
|
GitSuffix: ".git",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user