open-vault/physical/couchdb/couchdb_test.go
Alexander Scheel 8e6e53cf63
Use hashicorp mirror for container pulls (#17778)
When running the test suite in CI (where requests are centralized from
relatively few IPs), we'd occasionally hit Dockerhub's rate limits.
Luckily Hashicorp runs a (limited) public mirror of the containers we
need, so we can switch to them here in the tests.

For consistency between developer and CI, we've opted to have the tests
always pull from the Hashicorp mirror, rather than updating the CI
runner to prefer the mirror.

We exclude nomad and influxdb as we don't presently mirror these repos.

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
2022-11-02 13:33:17 -04:00

163 lines
4 KiB
Go

package couchdb
import (
"context"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"strings"
"testing"
"time"
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/helper/testhelpers/docker"
"github.com/hashicorp/vault/sdk/helper/logging"
"github.com/hashicorp/vault/sdk/physical"
)
func TestCouchDBBackend(t *testing.T) {
cleanup, config := prepareCouchdbDBTestContainer(t)
defer cleanup()
logger := logging.NewVaultLogger(log.Debug)
b, err := NewCouchDBBackend(map[string]string{
"endpoint": config.URL().String(),
"username": config.username,
"password": config.password,
}, logger)
if err != nil {
t.Fatalf("err: %s", err)
}
physical.ExerciseBackend(t, b)
physical.ExerciseBackend_ListPrefix(t, b)
}
func TestTransactionalCouchDBBackend(t *testing.T) {
cleanup, config := prepareCouchdbDBTestContainer(t)
defer cleanup()
logger := logging.NewVaultLogger(log.Debug)
b, err := NewTransactionalCouchDBBackend(map[string]string{
"endpoint": config.URL().String(),
"username": config.username,
"password": config.password,
}, logger)
if err != nil {
t.Fatalf("err: %s", err)
}
physical.ExerciseBackend(t, b)
physical.ExerciseBackend_ListPrefix(t, b)
}
type couchDB struct {
baseURL url.URL
dbname string
username string
password string
}
func (c couchDB) Address() string {
return c.baseURL.Host
}
func (c couchDB) URL() *url.URL {
u := c.baseURL
u.Path = c.dbname
return &u
}
var _ docker.ServiceConfig = &couchDB{}
func prepareCouchdbDBTestContainer(t *testing.T) (func(), *couchDB) {
// If environment variable is set, assume caller wants to target a real
// DynamoDB.
if os.Getenv("COUCHDB_ENDPOINT") != "" {
return func() {}, &couchDB{
baseURL: url.URL{Host: os.Getenv("COUCHDB_ENDPOINT")},
username: os.Getenv("COUCHDB_USERNAME"),
password: os.Getenv("COUCHDB_PASSWORD"),
}
}
runner, err := docker.NewServiceRunner(docker.RunOptions{
ContainerName: "couchdb",
ImageRepo: "docker.mirror.hashicorp.services/library/couchdb",
ImageTag: "1.6",
Ports: []string{"5984/tcp"},
DoNotAutoRemove: true,
})
if err != nil {
t.Fatalf("Could not start local CouchDB: %s", err)
}
svc, err := runner.StartService(context.Background(), setupCouchDB)
if err != nil {
t.Fatalf("Could not start local CouchDB: %s", err)
}
return svc.Cleanup, svc.Config.(*couchDB)
}
func setupCouchDB(ctx context.Context, host string, port int) (docker.ServiceConfig, error) {
c := &couchDB{
baseURL: url.URL{Scheme: "http", Host: fmt.Sprintf("%s:%d", host, port)},
dbname: fmt.Sprintf("vault-test-%d", time.Now().Unix()),
username: "admin",
password: "admin",
}
{
resp, err := http.Get(c.baseURL.String())
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("expected couchdb to return status code 200, got (%s) instead", resp.Status)
}
}
{
req, err := http.NewRequest("PUT", c.URL().String(), nil)
if err != nil {
return nil, fmt.Errorf("could not create create database request: %q", err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, fmt.Errorf("could not create database: %q", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusCreated {
bs, _ := ioutil.ReadAll(resp.Body)
return nil, fmt.Errorf("failed to create database: %s %s\n", resp.Status, string(bs))
}
}
{
u := c.baseURL
u.Path = fmt.Sprintf("_config/admins/%s", c.username)
req, err := http.NewRequest("PUT", u.String(), strings.NewReader(fmt.Sprintf(`"%s"`, c.password)))
if err != nil {
return nil, fmt.Errorf("Could not create admin user request: %q", err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, fmt.Errorf("Could not create admin user: %q", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
bs, _ := ioutil.ReadAll(resp.Body)
return nil, fmt.Errorf("Failed to create admin user: %s %s\n", resp.Status, string(bs))
}
}
return c, nil
}