148 lines
5.9 KiB
Go
148 lines
5.9 KiB
Go
package bootstrap
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"flag"
|
|
"slices"
|
|
"testing"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
|
|
databasev1alpha1 "git.ddupan.top/panxiao81/ayatori/api/database/v1alpha1"
|
|
executionv1alpha1 "git.ddupan.top/panxiao81/ayatori/api/execution/v1alpha1"
|
|
)
|
|
|
|
func parseTestOptions(t *testing.T, args ...string) options {
|
|
t.Helper()
|
|
flags := flag.NewFlagSet("bootstrap-test", flag.ContinueOnError)
|
|
var options options
|
|
options.bindFlags(flags)
|
|
if err := flags.Parse(args); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return options
|
|
}
|
|
|
|
func TestDefaultConfiguration(t *testing.T) {
|
|
t.Setenv("POD_NAMESPACE", "")
|
|
options := parseTestOptions(t)
|
|
manager := options.manager.configuration()
|
|
if manager.Metrics.BindAddress != "0" || !manager.Metrics.SecureServing || manager.Metrics.FilterProvider == nil {
|
|
t.Fatal("metrics defaults or authentication changed")
|
|
}
|
|
if manager.HealthProbeBindAddress != ":8081" || manager.LeaderElection ||
|
|
manager.LeaderElectionID != "a6325ed6.ddupan.top" || manager.LeaderElectionReleaseOnCancel {
|
|
t.Fatal("probe or leader election defaults changed")
|
|
}
|
|
if options.manager.webhookOptions().Port != 9443 || !options.logging.Development {
|
|
t.Fatal("webhook or logging defaults changed")
|
|
}
|
|
if options.database.secretNamespace != "" || options.database.credentialMount != "" || options.openBao.address != "" {
|
|
t.Fatal("optional backends enabled by default")
|
|
}
|
|
if options.openBao.mount != "kubernetes" || options.openBao.identity.Audience != "openbao" {
|
|
t.Fatal("OpenBao defaults changed")
|
|
}
|
|
options.database.configureManager(&manager)
|
|
if len(manager.Cache.ByObject) != 0 {
|
|
t.Fatal("disabled observation unexpectedly configured Secret cache")
|
|
}
|
|
for _, object := range []runtime.Object{
|
|
&corev1.Secret{}, &corev1.ServiceAccount{}, &executionv1alpha1.Job{},
|
|
&databasev1alpha1.PostgreSQLInstance{}, &databasev1alpha1.PostgreSQLDatabase{}, &databasev1alpha1.PostgreSQLTenant{},
|
|
} {
|
|
if _, _, err := manager.Scheme.ObjectKinds(object); err != nil {
|
|
t.Fatalf("missing scheme registration for %T: %v", object, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCredentialPreparationOptions(t *testing.T) {
|
|
options := parseTestOptions(t, "--database-credential-mount=applications-kv", "--database-credential-prefix=database")
|
|
if options.database.credentialMount != "applications-kv" || options.database.credentialPrefix != "database" {
|
|
t.Fatal("凭据准备参数未传入领域装配")
|
|
}
|
|
if err := setupCredentialPreparation(nil, options.database, nil); err == nil {
|
|
t.Fatal("启用凭据准备必须有显式配置的认证 client")
|
|
}
|
|
if err := setupCredentialPreparation(nil, databaseOptions{}, nil); err != nil {
|
|
t.Fatal("默认停用凭据准备不应要求后端")
|
|
}
|
|
}
|
|
|
|
func TestManagerFlagOverrides(t *testing.T) {
|
|
options := parseTestOptions(t,
|
|
"--metrics-bind-address=:9090", "--metrics-secure=false", "--health-probe-bind-address=:9091",
|
|
"--leader-elect", "--webhook-port=-1", "--metrics-cert-path=/fixture/metrics",
|
|
"--metrics-cert-name=server.crt", "--metrics-cert-key=server.key", "--webhook-cert-path=/fixture/webhook",
|
|
"--webhook-cert-name=hook.crt", "--webhook-cert-key=hook.key",
|
|
)
|
|
manager := options.manager.configuration()
|
|
if manager.Metrics.BindAddress != ":9090" || manager.Metrics.SecureServing || manager.Metrics.FilterProvider != nil ||
|
|
manager.HealthProbeBindAddress != ":9091" || !manager.LeaderElection {
|
|
t.Fatal("manager flags not applied")
|
|
}
|
|
if manager.Metrics.CertDir != "/fixture/metrics" || manager.Metrics.CertName != "server.crt" || manager.Metrics.KeyName != "server.key" {
|
|
t.Fatal("metrics certificate flags not applied")
|
|
}
|
|
webhook := options.manager.webhookOptions()
|
|
if webhook.Port != -1 || webhook.CertDir != "/fixture/webhook" || webhook.CertName != "hook.crt" || webhook.KeyName != "hook.key" {
|
|
t.Fatal("webhook flags not applied")
|
|
}
|
|
}
|
|
|
|
func TestHTTP2Policy(t *testing.T) {
|
|
for _, enabled := range []bool{false, true} {
|
|
args := []string{}
|
|
if enabled {
|
|
args = append(args, "--enable-http2")
|
|
}
|
|
options := parseTestOptions(t, args...)
|
|
for _, callbacks := range [][]func(*tls.Config){options.manager.metricsOptions().TLSOpts, options.manager.webhookOptions().TLSOpts} {
|
|
config := &tls.Config{NextProtos: []string{"h2", "http/1.1"}}
|
|
for _, callback := range callbacks {
|
|
callback(config)
|
|
}
|
|
if slices.Contains(config.NextProtos, "h2") != enabled || !slices.Contains(config.NextProtos, "http/1.1") {
|
|
t.Fatal("HTTP/2 policy changed")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestComponentFlagsAndNamespaceScope(t *testing.T) {
|
|
t.Setenv("POD_NAMESPACE", "from-environment")
|
|
if parseTestOptions(t).database.secretNamespace != "from-environment" {
|
|
t.Fatal("namespace environment default lost")
|
|
}
|
|
options := parseTestOptions(t,
|
|
"--database-secret-namespace=controller", "--database-root-cert=/fixture/postgres-ca.pem",
|
|
"--openbao-address=https://bao.example", "--openbao-ca-cert=/fixture/bao-ca.pem",
|
|
"--openbao-auth-mount=cluster", "--openbao-auth-role=controller",
|
|
"--openbao-service-account-namespace=identity", "--openbao-service-account-name=bao-login",
|
|
"--openbao-token-audience=bao",
|
|
)
|
|
if options.database.secretNamespace != "controller" || options.database.rootCert != "/fixture/postgres-ca.pem" {
|
|
t.Fatal("Database flags not applied")
|
|
}
|
|
bao := options.openBao
|
|
if bao.address != "https://bao.example" || bao.caCert != "/fixture/bao-ca.pem" || bao.mount != "cluster" ||
|
|
bao.role != "controller" || bao.identity.Namespace != "identity" || bao.identity.ServiceAccount != "bao-login" || bao.identity.Audience != "bao" {
|
|
t.Fatal("OpenBao flags not applied")
|
|
}
|
|
manager := options.manager.configuration()
|
|
options.database.configureManager(&manager)
|
|
if len(manager.Cache.ByObject) != 1 {
|
|
t.Fatal("Secret cache scope missing")
|
|
}
|
|
for object, config := range manager.Cache.ByObject {
|
|
if _, ok := object.(*corev1.Secret); !ok {
|
|
t.Fatal("unexpected cache object")
|
|
}
|
|
if _, ok := config.Namespaces["controller"]; !ok || len(config.Namespaces) != 1 {
|
|
t.Fatal("Secret cache escaped explicit namespace")
|
|
}
|
|
}
|
|
}
|