layer1: fix sa namespace routing step 2

This commit is contained in:
Naeel
2026-04-26 09:32:08 +03:00
parent c987fa07e8
commit 9ce9829f3b
3 changed files with 75 additions and 7 deletions
@@ -0,0 +1,33 @@
# 2026-04-26 — NamespaceManager rewrite, step 2
## Цель шага
Убрать еще один прямой проход по `FissionResourceNS` и закрыть конкретный баг в
`pkg/utils/serviceaccount.go`.
## Проблема
`runSACheck()` сейчас:
1. итерируется по `sa.nsResolver.FissionResourceNS` напрямую;
2. переиспользует переменную `ns` внутри внутреннего цикла по permissions.
Из-за этого код выглядит безобидно, но фактически смешивает два разных namespace path:
- fetcher path через `GetFunctionNS()`;
- builder path через `GetBuilderNS()`.
Если `FunctionNamespace` и `BuilderNamespace` различаются, builder SA может начать
резолвиться уже не от исходного namespace, а от результата предыдущего шага цикла.
## Что меняем
1. Берем base namespaces через thread-safe `Snapshot()`.
2. Для каждого permission вычисляем `targetNS` из исходного `baseNS`, а не из мутированной переменной.
3. Добавляем unit test на routing function/builder namespace.
## Что НЕ меняем на этом шаге
- не трогаем глобальные `fetcherCheck` / `builderCheck` структуры;
- не меняем `LocalSubjectAccessReview` path;
- не делаем большой refactor всего SA provisioning.
+31
View File
@@ -262,6 +262,37 @@ func TestNamespaceResolver(t *testing.T) {
})
}
func TestServiceAccountResolveSANamespace(t *testing.T) {
sa := &ServiceAccount{
nsResolver: &NamespaceResolver{
FunctionNamespace: "fission-function",
BuilderNamespace: "fission-builder",
DefaultNamespace: "default",
},
}
t.Run("fetcher uses function namespace for default ns", func(t *testing.T) {
resolvedNS := sa.resolveSANamespace("default", FetcherSAName)
if resolvedNS != "fission-function" {
t.Fatalf("expected function namespace, got %s", resolvedNS)
}
})
t.Run("builder uses builder namespace for default ns", func(t *testing.T) {
resolvedNS := sa.resolveSANamespace("default", BuilderSAName)
if resolvedNS != "fission-builder" {
t.Fatalf("expected builder namespace, got %s", resolvedNS)
}
})
t.Run("builder keeps tenant namespace unchanged", func(t *testing.T) {
resolvedNS := sa.resolveSANamespace("tenant-a", BuilderSAName)
if resolvedNS != "tenant-a" {
t.Fatalf("expected tenant namespace, got %s", resolvedNS)
}
})
}
func getFissionNamespaces(builderNS, functionNS, defaultNS string) *NamespaceResolver {
return &NamespaceResolver{
FunctionNamespace: functionNS,
+11 -7
View File
@@ -118,18 +118,22 @@ func getSAObj(kubernetesClient kubernetes.Interface, logger *zap.Logger) *Servic
}
func (sa *ServiceAccount) runSACheck(ctx context.Context) {
for _, ns := range sa.nsResolver.FissionResourceNS {
for _, baseNS := range sa.nsResolver.Snapshot() {
for _, permission := range sa.permissions {
if permission.saName == BuilderSAName {
ns = sa.nsResolver.GetBuilderNS(ns)
} else {
ns = sa.nsResolver.GetFunctionNS(ns)
}
setupSAAndRoleBindings(ctx, sa.kubernetesClient, sa.logger, ns, permission)
targetNS := sa.resolveSANamespace(baseNS, permission.saName)
setupSAAndRoleBindings(ctx, sa.kubernetesClient, sa.logger, targetNS, permission)
}
}
}
func (sa *ServiceAccount) resolveSANamespace(baseNS, saName string) string {
if saName == BuilderSAName {
return sa.nsResolver.GetBuilderNS(baseNS)
}
return sa.nsResolver.GetFunctionNS(baseNS)
}
func setupSAAndRoleBindings(ctx context.Context, client kubernetes.Interface, logger *zap.Logger, namespace string, ps *ServiceAccountPermissions) {
SAObj, err := createGetSA(ctx, client, ps.saName, namespace)
if err != nil {