mirror of
https://github.com/goharbor/harbor
synced 2025-04-22 19:10:40 +00:00
add ping for adapter to wait for service ready
Signed-off-by: wang yan <wangyan@vmware.com>
This commit is contained in:
parent
6e11ecc6fc
commit
b9d6108624
@ -34,8 +34,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
timeout = 60 * time.Second
|
timeout = 60 * time.Second
|
||||||
healthCheckerRegistry = map[string]health.Checker{}
|
// HealthCheckerRegistry ...
|
||||||
|
HealthCheckerRegistry = map[string]health.Checker{}
|
||||||
)
|
)
|
||||||
|
|
||||||
type overallHealthStatus struct {
|
type overallHealthStatus struct {
|
||||||
@ -67,11 +68,11 @@ type HealthAPI struct {
|
|||||||
func (h *HealthAPI) CheckHealth() {
|
func (h *HealthAPI) CheckHealth() {
|
||||||
var isHealthy healthy = true
|
var isHealthy healthy = true
|
||||||
components := []*componentHealthStatus{}
|
components := []*componentHealthStatus{}
|
||||||
c := make(chan *componentHealthStatus, len(healthCheckerRegistry))
|
c := make(chan *componentHealthStatus, len(HealthCheckerRegistry))
|
||||||
for name, checker := range healthCheckerRegistry {
|
for name, checker := range HealthCheckerRegistry {
|
||||||
go check(name, checker, timeout, c)
|
go check(name, checker, timeout, c)
|
||||||
}
|
}
|
||||||
for i := 0; i < len(healthCheckerRegistry); i++ {
|
for i := 0; i < len(HealthCheckerRegistry); i++ {
|
||||||
componentStatus := <-c
|
componentStatus := <-c
|
||||||
if len(componentStatus.Error) != 0 {
|
if len(componentStatus.Error) != 0 {
|
||||||
isHealthy = false
|
isHealthy = false
|
||||||
@ -290,21 +291,21 @@ func redisHealthChecker() health.Checker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func registerHealthCheckers() {
|
func registerHealthCheckers() {
|
||||||
healthCheckerRegistry["core"] = coreHealthChecker()
|
HealthCheckerRegistry["core"] = coreHealthChecker()
|
||||||
healthCheckerRegistry["portal"] = portalHealthChecker()
|
HealthCheckerRegistry["portal"] = portalHealthChecker()
|
||||||
healthCheckerRegistry["jobservice"] = jobserviceHealthChecker()
|
HealthCheckerRegistry["jobservice"] = jobserviceHealthChecker()
|
||||||
healthCheckerRegistry["registry"] = registryHealthChecker()
|
HealthCheckerRegistry["registry"] = registryHealthChecker()
|
||||||
healthCheckerRegistry["registryctl"] = registryCtlHealthChecker()
|
HealthCheckerRegistry["registryctl"] = registryCtlHealthChecker()
|
||||||
healthCheckerRegistry["database"] = databaseHealthChecker()
|
HealthCheckerRegistry["database"] = databaseHealthChecker()
|
||||||
healthCheckerRegistry["redis"] = redisHealthChecker()
|
HealthCheckerRegistry["redis"] = redisHealthChecker()
|
||||||
if config.WithChartMuseum() {
|
if config.WithChartMuseum() {
|
||||||
healthCheckerRegistry["chartmuseum"] = chartmuseumHealthChecker()
|
HealthCheckerRegistry["chartmuseum"] = chartmuseumHealthChecker()
|
||||||
}
|
}
|
||||||
if config.WithClair() {
|
if config.WithClair() {
|
||||||
healthCheckerRegistry["clair"] = clairHealthChecker()
|
HealthCheckerRegistry["clair"] = clairHealthChecker()
|
||||||
}
|
}
|
||||||
if config.WithNotary() {
|
if config.WithNotary() {
|
||||||
healthCheckerRegistry["notary"] = notaryHealthChecker()
|
HealthCheckerRegistry["notary"] = notaryHealthChecker()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,9 +92,9 @@ func fakeHealthChecker(healthy bool) health.Checker {
|
|||||||
}
|
}
|
||||||
func TestCheckHealth(t *testing.T) {
|
func TestCheckHealth(t *testing.T) {
|
||||||
// component01: healthy, component02: healthy => status: healthy
|
// component01: healthy, component02: healthy => status: healthy
|
||||||
healthCheckerRegistry = map[string]health.Checker{}
|
HealthCheckerRegistry = map[string]health.Checker{}
|
||||||
healthCheckerRegistry["component01"] = fakeHealthChecker(true)
|
HealthCheckerRegistry["component01"] = fakeHealthChecker(true)
|
||||||
healthCheckerRegistry["component02"] = fakeHealthChecker(true)
|
HealthCheckerRegistry["component02"] = fakeHealthChecker(true)
|
||||||
status := map[string]interface{}{}
|
status := map[string]interface{}{}
|
||||||
err := handleAndParse(&testingRequest{
|
err := handleAndParse(&testingRequest{
|
||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
@ -104,9 +104,9 @@ func TestCheckHealth(t *testing.T) {
|
|||||||
assert.Equal(t, "healthy", status["status"].(string))
|
assert.Equal(t, "healthy", status["status"].(string))
|
||||||
|
|
||||||
// component01: healthy, component02: unhealthy => status: unhealthy
|
// component01: healthy, component02: unhealthy => status: unhealthy
|
||||||
healthCheckerRegistry = map[string]health.Checker{}
|
HealthCheckerRegistry = map[string]health.Checker{}
|
||||||
healthCheckerRegistry["component01"] = fakeHealthChecker(true)
|
HealthCheckerRegistry["component01"] = fakeHealthChecker(true)
|
||||||
healthCheckerRegistry["component02"] = fakeHealthChecker(false)
|
HealthCheckerRegistry["component02"] = fakeHealthChecker(false)
|
||||||
status = map[string]interface{}{}
|
status = map[string]interface{}{}
|
||||||
err = handleAndParse(&testingRequest{
|
err = handleAndParse(&testingRequest{
|
||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
@ -128,7 +128,7 @@ func TestDatabaseHealthChecker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRegisterHealthCheckers(t *testing.T) {
|
func TestRegisterHealthCheckers(t *testing.T) {
|
||||||
healthCheckerRegistry = map[string]health.Checker{}
|
HealthCheckerRegistry = map[string]health.Checker{}
|
||||||
registerHealthCheckers()
|
registerHealthCheckers()
|
||||||
assert.NotNil(t, healthCheckerRegistry["core"])
|
assert.NotNil(t, HealthCheckerRegistry["core"])
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"github.com/goharbor/harbor/src/common/models"
|
"github.com/goharbor/harbor/src/common/models"
|
||||||
common_quota "github.com/goharbor/harbor/src/common/quota"
|
common_quota "github.com/goharbor/harbor/src/common/quota"
|
||||||
"github.com/goharbor/harbor/src/common/utils/log"
|
"github.com/goharbor/harbor/src/common/utils/log"
|
||||||
|
"github.com/goharbor/harbor/src/core/api"
|
||||||
quota "github.com/goharbor/harbor/src/core/api/quota"
|
quota "github.com/goharbor/harbor/src/core/api/quota"
|
||||||
"github.com/goharbor/harbor/src/core/config"
|
"github.com/goharbor/harbor/src/core/config"
|
||||||
"github.com/goharbor/harbor/src/core/promgr"
|
"github.com/goharbor/harbor/src/core/promgr"
|
||||||
@ -49,6 +50,11 @@ var (
|
|||||||
controllerOnce sync.Once
|
controllerOnce sync.Once
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Ping ...
|
||||||
|
func (rm *Migrator) Ping() error {
|
||||||
|
return api.HealthCheckerRegistry["chartmuseum"].Check()
|
||||||
|
}
|
||||||
|
|
||||||
// Dump ...
|
// Dump ...
|
||||||
// Depends on DB to dump chart data, as chart cannot get all of namespaces.
|
// Depends on DB to dump chart data, as chart cannot get all of namespaces.
|
||||||
func (rm *Migrator) Dump() ([]quota.ProjectInfo, error) {
|
func (rm *Migrator) Dump() ([]quota.ProjectInfo, error) {
|
||||||
@ -99,8 +105,6 @@ func (rm *Migrator) Dump() ([]quota.ProjectInfo, error) {
|
|||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
var repos []quota.RepoData
|
var repos []quota.RepoData
|
||||||
var afs []*models.Artifact
|
|
||||||
|
|
||||||
ctr, err := chartController()
|
ctr, err := chartController()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errChan <- err
|
errChan <- err
|
||||||
@ -115,6 +119,7 @@ func (rm *Migrator) Dump() ([]quota.ProjectInfo, error) {
|
|||||||
|
|
||||||
// repo
|
// repo
|
||||||
for _, chart := range chartInfo {
|
for _, chart := range chartInfo {
|
||||||
|
var afs []*models.Artifact
|
||||||
chartVersions, err := ctr.GetChart(project.Name, chart.Name)
|
chartVersions, err := ctr.GetChart(project.Name, chart.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errChan <- err
|
errChan <- err
|
||||||
@ -171,7 +176,8 @@ func (rm *Migrator) Usage(projects []quota.ProjectInfo) ([]quota.ProjectUsage, e
|
|||||||
proUsage := quota.ProjectUsage{
|
proUsage := quota.ProjectUsage{
|
||||||
Project: project.Name,
|
Project: project.Name,
|
||||||
Used: common_quota.ResourceList{
|
Used: common_quota.ResourceList{
|
||||||
common_quota.ResourceCount: count,
|
common_quota.ResourceCount: count,
|
||||||
|
common_quota.ResourceStorage: 0,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
pros = append(pros, proUsage)
|
pros = append(pros, proUsage)
|
||||||
|
@ -21,11 +21,15 @@ import (
|
|||||||
"github.com/goharbor/harbor/src/common/utils/log"
|
"github.com/goharbor/harbor/src/common/utils/log"
|
||||||
"github.com/goharbor/harbor/src/core/config"
|
"github.com/goharbor/harbor/src/core/config"
|
||||||
"github.com/goharbor/harbor/src/core/promgr"
|
"github.com/goharbor/harbor/src/core/promgr"
|
||||||
|
"github.com/goharbor/harbor/src/pkg/types"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// QuotaMigrator ...
|
// QuotaMigrator ...
|
||||||
type QuotaMigrator interface {
|
type QuotaMigrator interface {
|
||||||
|
// Ping validates and wait for backend service ready.
|
||||||
|
Ping() error
|
||||||
|
|
||||||
// Dump exports all data from backend service, registry, chartmuseum
|
// Dump exports all data from backend service, registry, chartmuseum
|
||||||
Dump() ([]ProjectInfo, error)
|
Dump() ([]ProjectInfo, error)
|
||||||
|
|
||||||
@ -74,6 +78,7 @@ func Register(name string, adapter Instance) {
|
|||||||
|
|
||||||
// Sync ...
|
// Sync ...
|
||||||
func Sync(pm promgr.ProjectManager, populate bool) error {
|
func Sync(pm promgr.ProjectManager, populate bool) error {
|
||||||
|
totalUsage := make(map[string][]ProjectUsage)
|
||||||
for name, instanceFunc := range adapters {
|
for name, instanceFunc := range adapters {
|
||||||
if !config.WithChartMuseum() {
|
if !config.WithChartMuseum() {
|
||||||
if name == "chart" {
|
if name == "chart" {
|
||||||
@ -81,6 +86,9 @@ func Sync(pm promgr.ProjectManager, populate bool) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
adapter := instanceFunc(pm)
|
adapter := instanceFunc(pm)
|
||||||
|
if err := adapter.Ping(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
data, err := adapter.Dump()
|
data, err := adapter.Dump()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -89,18 +97,58 @@ func Sync(pm promgr.ProjectManager, populate bool) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ensureQuota(usage); err != nil {
|
totalUsage[name] = usage
|
||||||
return err
|
|
||||||
}
|
|
||||||
if populate {
|
if populate {
|
||||||
if err := adapter.Persist(data); err != nil {
|
if err := adapter.Persist(data); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
merged := mergeUsage(totalUsage)
|
||||||
|
if err := ensureQuota(merged); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mergeUsage merges the usage of adapters
|
||||||
|
func mergeUsage(total map[string][]ProjectUsage) []ProjectUsage {
|
||||||
|
if !config.WithChartMuseum() {
|
||||||
|
return total["registry"]
|
||||||
|
}
|
||||||
|
regUsgs := total["registry"]
|
||||||
|
chartUsgs := total["chart"]
|
||||||
|
|
||||||
|
var mergedUsage []ProjectUsage
|
||||||
|
temp := make(map[string]quota.ResourceList)
|
||||||
|
|
||||||
|
for _, regUsg := range regUsgs {
|
||||||
|
_, exist := temp[regUsg.Project]
|
||||||
|
if !exist {
|
||||||
|
temp[regUsg.Project] = regUsg.Used
|
||||||
|
mergedUsage = append(mergedUsage, ProjectUsage{
|
||||||
|
Project: regUsg.Project,
|
||||||
|
Used: regUsg.Used,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, chartUsg := range chartUsgs {
|
||||||
|
var usedTemp quota.ResourceList
|
||||||
|
_, exist := temp[chartUsg.Project]
|
||||||
|
if !exist {
|
||||||
|
usedTemp = chartUsg.Used
|
||||||
|
} else {
|
||||||
|
usedTemp = types.Add(temp[chartUsg.Project], chartUsg.Used)
|
||||||
|
}
|
||||||
|
temp[chartUsg.Project] = usedTemp
|
||||||
|
mergedUsage = append(mergedUsage, ProjectUsage{
|
||||||
|
Project: chartUsg.Project,
|
||||||
|
Used: usedTemp,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return mergedUsage
|
||||||
|
}
|
||||||
|
|
||||||
// ensureQuota updates the quota and quota usage in the data base.
|
// ensureQuota updates the quota and quota usage in the data base.
|
||||||
func ensureQuota(usages []ProjectUsage) error {
|
func ensureQuota(usages []ProjectUsage) error {
|
||||||
var pid int64
|
var pid int64
|
||||||
|
@ -46,6 +46,11 @@ func NewRegistryMigrator(pm promgr.ProjectManager) quota.QuotaMigrator {
|
|||||||
return &migrator
|
return &migrator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ping ...
|
||||||
|
func (rm *Migrator) Ping() error {
|
||||||
|
return api.HealthCheckerRegistry["registry"].Check()
|
||||||
|
}
|
||||||
|
|
||||||
// Dump ...
|
// Dump ...
|
||||||
func (rm *Migrator) Dump() ([]quota.ProjectInfo, error) {
|
func (rm *Migrator) Dump() ([]quota.ProjectInfo, error) {
|
||||||
var (
|
var (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user