Fix replication failure in kubernetes with hairpin mode disabled

Fixes #11480
Fixes #11461
Fix replication failure in kubernetes with hairpin mode disabled

Signed-off-by: Wenkai Yin <yinw@vmware.com>
This commit is contained in:
Wenkai Yin 2020-04-07 23:36:38 +08:00
parent bf6c4ff1f1
commit 8ee3421176
5 changed files with 48 additions and 25 deletions

View File

@ -17,6 +17,7 @@ package base
import (
"errors"
"net/http"
"os"
"strconv"
"strings"
@ -32,7 +33,7 @@ import (
// New creates an instance of the base adapter
func New(registry *model.Registry) (*Adapter, error) {
if isLocalHarbor(registry) {
if isLocalHarbor(registry.URL) {
authorizer := common_http_auth.NewSecretAuthorizer(registry.Credential.AccessSecret)
httpClient := common_http.NewClient(&http.Client{
Transport: common_http.GetHTTPTransport(common_http.SecureTransport),
@ -266,6 +267,11 @@ type Project struct {
Metadata map[string]interface{} `json:"metadata"`
}
func isLocalHarbor(registry *model.Registry) bool {
return registry.Type == model.RegistryTypeHarbor && registry.Name == "Local"
func isLocalHarbor(url string) bool {
return url == os.Getenv("CORE_URL")
}
// check whether the current process is running inside core
func isInCore() bool {
return len(os.Getenv("EXT_ENDPOINT")) > 0
}

View File

@ -54,7 +54,7 @@ func (a *Adapter) FetchCharts(filters []*model.Filter) ([]*model.Resource, error
resources := []*model.Resource{}
for _, project := range projects {
url := fmt.Sprintf("%s/api/chartrepo/%s/charts", a.url, project.Name)
url := fmt.Sprintf("%s/api/chartrepo/%s/charts", a.Client.GetURL(), project.Name)
repositories := []*model.Repository{}
if err := a.httpClient.Get(url, &repositories); err != nil {
return nil, err
@ -72,7 +72,7 @@ func (a *Adapter) FetchCharts(filters []*model.Filter) ([]*model.Resource, error
for _, repository := range repositories {
name := strings.SplitN(repository.Name, "/", 2)[1]
url := fmt.Sprintf("%s/api/chartrepo/%s/charts/%s", a.url, project.Name, name)
url := fmt.Sprintf("%s/api/chartrepo/%s/charts/%s", a.Client.GetURL(), project.Name, name)
versions := []*chartVersion{}
if err := a.httpClient.Get(url, &versions); err != nil {
return nil, err
@ -134,7 +134,7 @@ func (a *Adapter) getChartInfo(name, version string) (*chartVersionDetail, error
if err != nil {
return nil, err
}
url := fmt.Sprintf("%s/api/chartrepo/%s/charts/%s/%s", a.url, project, name, version)
url := fmt.Sprintf("%s/api/chartrepo/%s/charts/%s/%s", a.Client.GetURL(), project, name, version)
info := &chartVersionDetail{}
if err = a.httpClient.Get(url, info); err != nil {
return nil, err
@ -158,7 +158,7 @@ func (a *Adapter) DownloadChart(name, version string) (io.ReadCloser, error) {
if err != nil {
return nil, err
}
url = fmt.Sprintf("%s/chartrepo/%s/%s", a.url, project, url)
url = fmt.Sprintf("%s/chartrepo/%s/%s", a.Client.GetURL(), project, url)
}
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
@ -196,7 +196,7 @@ func (a *Adapter) UploadChart(name, version string, chart io.Reader) error {
}
w.Close()
url := fmt.Sprintf("%s/api/chartrepo/%s/charts", a.url, project)
url := fmt.Sprintf("%s/api/chartrepo/%s/charts", a.Client.GetURL(), project)
req, err := http.NewRequest(http.MethodPost, url, buf)
if err != nil {
@ -228,7 +228,7 @@ func (a *Adapter) DeleteChart(name, version string) error {
if err != nil {
return err
}
url := fmt.Sprintf("%s/api/chartrepo/%s/charts/%s/%s", a.url, project, name, version)
url := fmt.Sprintf("%s/api/chartrepo/%s/charts/%s/%s", a.Client.GetURL(), project, name, version)
return a.httpClient.Delete(url)
}

View File

@ -48,7 +48,7 @@ func (c *Client) GetAPIVersion() (string, error) {
version := &struct {
Version string `json:"version"`
}{}
err := c.C.Get(c.URL+"/api/version", version)
err := c.C.Get(c.GetURL()+"/api/version", version)
if err == nil {
return version.Version, nil
}
@ -64,7 +64,7 @@ func (c *Client) ChartRegistryEnabled() (bool, error) {
sys := &struct {
ChartRegistryEnabled bool `json:"with_chartmuseum"`
}{}
if err := c.C.Get(c.BaseURL()+"/systeminfo", sys); err != nil {
if err := c.C.Get(c.BasePath()+"/systeminfo", sys); err != nil {
return false, err
}
return sys.ChartRegistryEnabled, nil
@ -75,7 +75,7 @@ func (c *Client) ListLabels() ([]string, error) {
labels := []*struct {
Name string `json:"name"`
}{}
err := c.C.Get(c.BaseURL()+"/labels?scope=g", &labels)
err := c.C.Get(c.BasePath()+"/labels?scope=g", &labels)
if err == nil {
var lbs []string
for _, label := range labels {
@ -99,13 +99,13 @@ func (c *Client) CreateProject(name string, metadata map[string]interface{}) err
Name: name,
Metadata: metadata,
}
return c.C.Post(c.BaseURL()+"/projects", project)
return c.C.Post(c.BasePath()+"/projects", project)
}
// ListProjects lists projects
func (c *Client) ListProjects(name string) ([]*Project, error) {
projects := []*Project{}
url := fmt.Sprintf("%s/projects?name=%s", c.BaseURL(), name)
url := fmt.Sprintf("%s/projects?name=%s", c.BasePath(), name)
if err := c.C.GetAndIteratePagination(url, &projects); err != nil {
return nil, err
}
@ -126,10 +126,27 @@ func (c *Client) GetProject(name string) (*Project, error) {
return nil, nil
}
// BaseURL returns the base URL of APIs
func (c *Client) BaseURL() string {
if len(c.APIVersion) == 0 {
return fmt.Sprintf("%s/api", c.URL)
// BasePath returns the API base path that contains version part
func (c *Client) BasePath() string {
path := fmt.Sprintf("%s/api", c.GetURL())
if len(c.APIVersion) > 0 {
path = fmt.Sprintf("%s/%s", path, c.APIVersion)
}
return fmt.Sprintf("%s/api/%s", c.URL, c.APIVersion)
return path
}
// GetURL returns the URL of the registry that the client is for
func (c *Client) GetURL() string {
if !isLocalHarbor(c.URL) || !isInCore() {
return c.URL
}
// if the adapter is created for local Harbor and the process is running
// inside core, returns the "127.0.0.1" as URL to avoid the issue:
// https://github.com/goharbor/harbor-helm/issues/222
// when harbor is deployed on Kubernetes with hairpin mode disabled
url := "http://127.0.0.1:8080"
if common_http.InternalTLSEnabled() {
url = "https://127.0.0.1:8443"
}
return url
}

View File

@ -28,7 +28,7 @@ type client struct {
func (c *client) listRepositories(project *base.Project) ([]*model.Repository, error) {
repositories := []*models.RepoRecord{}
url := fmt.Sprintf("%s/repositories?project_id=%d", c.BaseURL(), project.ID)
url := fmt.Sprintf("%s/repositories?project_id=%d", c.BasePath(), project.ID)
if err := c.C.GetAndIteratePagination(url, &repositories); err != nil {
return nil, err
}
@ -43,7 +43,7 @@ func (c *client) listRepositories(project *base.Project) ([]*model.Repository, e
}
func (c *client) listArtifacts(repository string) ([]*model.Artifact, error) {
url := fmt.Sprintf("%s/repositories/%s/tags", c.BaseURL(), repository)
url := fmt.Sprintf("%s/repositories/%s/tags", c.BasePath(), repository)
tags := []*struct {
Name string `json:"name"`
Labels []*struct {
@ -68,6 +68,6 @@ func (c *client) listArtifacts(repository string) ([]*model.Artifact, error) {
}
func (c *client) deleteManifest(repository, reference string) error {
url := fmt.Sprintf("%s/repositories/%s/tags/%s", c.BaseURL(), repository, reference)
url := fmt.Sprintf("%s/repositories/%s/tags/%s", c.BasePath(), repository, reference)
return c.C.Delete(url)
}

View File

@ -31,7 +31,7 @@ type client struct {
func (c *client) listRepositories(project *base.Project) ([]*model.Repository, error) {
repositories := []*models.RepoRecord{}
url := fmt.Sprintf("%s/projects/%s/repositories", c.BaseURL(), project.Name)
url := fmt.Sprintf("%s/projects/%s/repositories", c.BasePath(), project.Name)
if err := c.C.GetAndIteratePagination(url, &repositories); err != nil {
return nil, err
}
@ -49,7 +49,7 @@ func (c *client) listArtifacts(repository string) ([]*model.Artifact, error) {
project, repository := utils.ParseRepository(repository)
repository = url.PathEscape(url.PathEscape(repository))
url := fmt.Sprintf("%s/projects/%s/repositories/%s/artifacts?with_label=true",
c.BaseURL(), project, repository)
c.BasePath(), project, repository)
artifacts := []*artifact.Artifact{}
if err := c.C.GetAndIteratePagination(url, &artifacts); err != nil {
return nil, err
@ -75,6 +75,6 @@ func (c *client) deleteTag(repository, tag string) error {
project, repository := utils.ParseRepository(repository)
repository = url.PathEscape(url.PathEscape(repository))
url := fmt.Sprintf("%s/projects/%s/repositories/%s/artifacts/%s/tags/%s",
c.BaseURL(), project, repository, tag, tag)
c.BasePath(), project, repository, tag, tag)
return c.C.Delete(url)
}