helm-chart-genes/charts/harbor-helm-main/test/integration/base.go

189 lines
4.4 KiB
Go
Raw Normal View History

2024-04-16 17:08:47 +02:00
package integration
import (
"crypto/tls"
"encoding/json"
"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{
Timeout: 30*time.Second,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
}
)
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{}
}
return BaseTestSuite{
Options: &helm.Options{
KubectlOptions: &k8s.KubectlOptions{
Namespace: "default",
},
SetValues: values,
},
ReleaseName: fmt.Sprintf("harbor-%d", rand.Int()),
URL: values["externalURL"],
}
}
type BaseTestSuite struct {
suite.Suite
Options *helm.Options
ReleaseName string
URL string // the external URL of Harbor
}
func (b *BaseTestSuite) SetupSuite() {
helm.Install(b.T(), b.Options, "../..", b.ReleaseName)
b.waitUntilHealthy(b.URL)
}
type overallStatus struct {
Status string `json:"status"`
Components []*componentStatus `json:"components"`
}
type componentStatus struct {
Name string `json:"name"`
Status string `json:"status"`
Error string `json:"error,omitempty"`
}
func (b *BaseTestSuite) waitUntilHealthy(url string) {
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
}
}()
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")
}
}
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
}
return fmt.Errorf("the status of component %s isn't healthy: %s ", component.Name, component.Error)
}
return fmt.Errorf("the overall status is unhealthy, but all components are healthy")
}
return nil
}
func (b *BaseTestSuite) TestPush() {
addr := strings.TrimPrefix(b.URL, "http://")
addr = strings.TrimPrefix(addr, "https://")
// push 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)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
b.Require().Nil(err)
// delete 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
cmd.Stderr = os.Stderr
err = cmd.Run()
b.Require().Nil(err)
// pull 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
cmd.Stderr = os.Stderr
err = cmd.Run()
b.Require().Nil(err)
}
func (b *BaseTestSuite) TearDownSuite() {
helm.Delete(b.T(), b.Options, b.ReleaseName, true)
}