testcontainers-go module running a sharded kcp instance for tests.
A kcp-testcontainers instance is always deployed under the constraints the kcp project defines as the minimum viable architecture:
- At least one front-proxy
- At least two shards
- One cache-server
With the front-proxy and the shards' virtual workspaces being accessible to clients.
This testcontainer module is ideal to write integration or e2e tests for operators targeting kcp directly or a system utilizing kcp.
Import this module:
import kcptc "github.com/kcp-dev/kcp-testcontainers"Create an instance and create workspaces:
instance, err := kcptc.Run(ctx, kcptc.Options{})
// create workspaces (parents included)
path, err := instance.CreateWorkspace(ctx, "root:my:workspace")
// create workspace with generated name (parents included)
path, err = instance.CreateWorkspace(ctx, "root:test-")
// kcp's workspace options apply to the last workspace in the path; wait until
// the front-proxy serves every workspace in the path, not only until Ready
path, err = instance.CreateWorkspace(ctx, "root:org:team",
kcptc.With(kcptesting.WithType(logicalcluster.NewPath("root"), "organization")),
kcptc.WaitForReachable(),
)
// rest.Config for a workspace
cfg := instance.RESTConfig("root:my:workspace")
// controller-runtime client for a workspace
cl, err := instance.Client("root:my:workspace", client.Options{})
// rest.Config not scoped to a workspace, e.g. for a virtual workspace URL
// (every serving certificate is valid for the Docker host the ports are
// published on, so no TLS overrides are needed)
cfg = instance.BaseConfig()When running go tests each tested package is run as its own process.
kcptc.Shared implements sharing instances across processes by giving
an instance a name and using testcontainers SessionID:
// a shared instance that is reused across processes
shared, err := kcptc.Shared(ctx, "shared-instance", kcptc.Options{})
sharedWS, err := shared.CreateWorkspace(ctx, "root:my:workspace")
sharedCL, err := shared.Client("root:my:workspace", client.Options{})To prevent drift for the configurations a good option is to have
a framework package with functions that call Shared:
func Kcp(ctx context.Context) (*kcptc.Instance, error) {
return kcptc.Shared(ctx, "default", kcptc.Options{})
}
func KcpWithMigrations(ctx context.Context) (*kcptc.Instance, error) {
return kcptc.Shared(ctx, "second", kcptc.Options{
FeatureGates: []string{"LogicalClusterMigration"},
})
}