Skip to content

Commit

Permalink
Fix random CI failure in Github action
Browse files Browse the repository at this point in the history
1. Fix random CI failure in Github action
We install Harbor chart two times(one for testing ingress, the other one for testing node port) in the kind k8s cluster with the same release name "harbor", sometimes when running the testting for the node port, the service name "harbor-harbor-core" is resolved to the IP of service created in the testing for ingress. In this PR, we use different release names to avoid this
2. Refine some testing code
3. Update docs

Signed-off-by: Wenkai Yin <yinw@vmware.com>
  • Loading branch information
ywk253100 committed Nov 4, 2020
1 parent 1b676d6 commit 1274027
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 39 deletions.
2 changes: 1 addition & 1 deletion docs/High Availability.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Deploy Harbor on K8S via helm to make it highly available, that is, if one of no

## Prerequisites

- Kubernetes cluster 1.10+
- Kubernetes cluster 1.16+
- Helm 2.10.0+
- High available ingress controller (Harbor does not manage the external endpoint)
- High available PostgreSQL database (Harbor does not handle the deployment of HA of database)
Expand Down
2 changes: 1 addition & 1 deletion docs/Upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Configure the new chart to make sure that the configuration items have the same
kubectl create -f secret.yaml
```

5) Configure the chart to use the new secret by setting `expose.tls.secretName` as the value you set in step **3**
5) Configure the chart to use the new secret by setting `expose.tls.certSource` as `secret` and `expose.tls.secret.secretName` as the value you set in step **3**

### 4. Upgrade

Expand Down
116 changes: 79 additions & 37 deletions test/integration/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,26 @@ import (
"fmt"
"io/ioutil"
"log"
"math/rand"
"net/http"
"os"
"os/exec"
"strings"
"sync"
"time"

"github.com/gruntwork-io/terratest/modules/helm"
"github.com/gruntwork-io/terratest/modules/k8s"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/testing"
"github.com/stretchr/testify/suite"
)

func init() {
// override the default logger to make the log in the same style
logger.Default = logger.New(&Logger{})
}

var (
client = &http.Client{
Transport: &http.Transport{
Expand All @@ -27,6 +36,12 @@ var (
}
)

type Logger struct{}

func (l *Logger) Logf(t testing.TestingT, format string, args ...interface{}) {
log.Printf(format, args...)
}

func NewBaseTestSuite(values map[string]string) BaseTestSuite {
if values == nil {
values = map[string]string{}
Expand All @@ -38,7 +53,7 @@ func NewBaseTestSuite(values map[string]string) BaseTestSuite {
},
SetValues: values,
},
ReleaseName: "harbor",
ReleaseName: fmt.Sprintf("harbor-%d", rand.Int()),
URL: values["externalURL"],
}
}
Expand Down Expand Up @@ -67,52 +82,79 @@ type componentStatus struct {
}

func (b *BaseTestSuite) waitUntilHealthy(url string) {
url = fmt.Sprintf("%s/api/v2.0/health", url)
log.Printf("wait until Harbor is healthy by calling health check API: %s ...", url)
for i := 0; i < 60; i++ {
time.Sleep(10 * time.Second)

resp, err := client.Get(url)
if err != nil {
log.Printf("failed to call the health API: %v, retry 10 seconds later...", err)
continue
var (
timeout bool
done = make(chan struct{})
lock = sync.RWMutex{}
)
go func() {
log.Printf("wait until Harbor is healthy by calling the health check API ...")
stop := false
for !stop {
if err := healthy(url); err != nil {
log.Printf("the status of Harbor isn't healthy: %v, will retry 10 seconds later...", err)
time.Sleep(10 * time.Second)
lock.RLock()
stop = timeout
lock.RUnlock()
continue
}
log.Printf("the status of Harbor is healthy")
done <- struct{}{}
return
}
}()

if resp.StatusCode != http.StatusOK {
log.Printf("the response status code %d != 200, retry 10 seconds later...", resp.StatusCode)
continue
}
select {
case <-done:
return
case <-time.After(10 * time.Minute):
lock.Lock()
timeout = true
lock.Unlock()
log.Print("timeout when checking the status")
b.FailNow("timeout when checking the status")
}
}

data, err := ioutil.ReadAll(resp.Body)
b.Require().Nil(err)
resp.Body.Close()
status := &overallStatus{}
err = json.Unmarshal(data, status)
b.Require().Nil(err)
if status.Status != "healthy" {
for _, component := range status.Components {
if component.Status == "healthy" {
continue
}
log.Printf("the status of component %s isn't healthy: %s , retry 10 seconds later...",
component.Name, component.Error)
break
func healthy(url string) error {
resp, err := client.Get(fmt.Sprintf("%s/api/v2.0/health", url))
if err != nil {
return err
}
defer resp.Body.Close()

data, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}

if resp.StatusCode != http.StatusOK {
return fmt.Errorf("the response status code %d != 200, response body: %s", resp.StatusCode, string(data))
}

status := &overallStatus{}
if err = json.Unmarshal(data, status); err != nil {
return err
}
if status.Status != "healthy" {
for _, component := range status.Components {
if component.Status == "healthy" {
continue
}
continue
return fmt.Errorf("the status of component %s isn't healthy: %s ", component.Name, component.Error)
}

log.Printf("the status is healthy")
return
return fmt.Errorf("the overall status is unhealthy, but all components are healthy")
}
b.FailNow("the status still isn't healthy after several retries")
return nil
}

func (b *BaseTestSuite) TestPush() {
addr := strings.TrimPrefix(b.URL, "http://")
addr = strings.TrimPrefix(addr, "https://")

// push image
b.T().Log("pushing the image...")
log.Print("pushing the image...")
cmdStr := fmt.Sprintf("docker pull hello-world:latest;docker tag hello-world:latest %s/library/hello-world:latest; docker login %s -u admin -p Harbor12345;docker push %s/library/hello-world:latest",
addr, addr, addr)
cmd := exec.Command("/bin/sh", "-c", cmdStr)
Expand All @@ -122,7 +164,7 @@ func (b *BaseTestSuite) TestPush() {
b.Require().Nil(err)

// delete image in local
b.T().Log("deleting the image in local")
log.Print("deleting the image in local")
cmdStr = fmt.Sprintf("docker rmi %s/library/hello-world:latest", addr)
cmd = exec.Command("/bin/sh", "-c", cmdStr)
cmd.Stdout = os.Stdout
Expand All @@ -131,7 +173,7 @@ func (b *BaseTestSuite) TestPush() {
b.Require().Nil(err)

// pull image
b.T().Log("pull the image...")
log.Print("pull the image...")
cmdStr = fmt.Sprintf("docker pull %s/library/hello-world:latest", addr)
cmd = exec.Command("/bin/sh", "-c", cmdStr)
cmd.Stdout = os.Stdout
Expand All @@ -141,5 +183,5 @@ func (b *BaseTestSuite) TestPush() {
}

func (b *BaseTestSuite) TearDownSuite() {
helm.Delete(b.T(), &helm.Options{}, b.ReleaseName, true)
helm.Delete(b.T(), b.Options, b.ReleaseName, true)
}

0 comments on commit 1274027

Please sign in to comment.