From 44beedd09a50530a81c9afbea1eff190b6bfa6b9 Mon Sep 17 00:00:00 2001 From: Misi Date: Thu, 30 Oct 2025 16:50:40 +0100 Subject: [PATCH] IAM: Handle NULL external_uid, is_provisioned correctly for Teams (#113219) * Handle NULL external_uid correctly with MySQL * Add NULL handling to is_provisioned column --- pkg/registry/apis/iam/legacy/team.go | 21 ++++++++++---- pkg/tests/apis/iam/team_integration_test.go | 31 +++++++++++++++++++++ 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/pkg/registry/apis/iam/legacy/team.go b/pkg/registry/apis/iam/legacy/team.go index 51e68506fbd..874dea3dff9 100644 --- a/pkg/registry/apis/iam/legacy/team.go +++ b/pkg/registry/apis/iam/legacy/team.go @@ -2,6 +2,7 @@ package legacy import ( "context" + "database/sql" "errors" "fmt" "time" @@ -129,18 +130,18 @@ func (s *legacySQLStore) ListTeams(ctx context.Context, ns claims.NamespaceInfo, return nil, fmt.Errorf("expected non zero orgID") } - sql, err := s.sql(ctx) + sqlConn, err := s.sql(ctx) if err != nil { return nil, err } - req := newListTeams(sql, &query) + req := newListTeams(sqlConn, &query) q, err := sqltemplate.Execute(sqlQueryTeamsTemplate, req) if err != nil { return nil, fmt.Errorf("execute template %q: %w", sqlQueryTeamsTemplate.Name(), err) } - rows, err := sql.DB.GetSqlxSession().Query(ctx, q, req.GetArgs()...) + rows, err := sqlConn.DB.GetSqlxSession().Query(ctx, q, req.GetArgs()...) defer func() { if rows != nil { _ = rows.Close() @@ -155,11 +156,21 @@ func (s *legacySQLStore) ListTeams(ctx context.Context, ns claims.NamespaceInfo, var lastID int64 for rows.Next() { t := team.Team{} - err = rows.Scan(&t.ID, &t.UID, &t.Name, &t.Email, &t.ExternalUID, &t.IsProvisioned, &t.Created, &t.Updated) + var externalUID sql.NullString + var isProvisioned sql.NullBool + err = rows.Scan(&t.ID, &t.UID, &t.Name, &t.Email, &externalUID, &isProvisioned, &t.Created, &t.Updated) if err != nil { return res, err } + if externalUID.Valid { + t.ExternalUID = externalUID.String + } + + if isProvisioned.Valid { + t.IsProvisioned = isProvisioned.Bool + } + lastID = t.ID res.Teams = append(res.Teams, t) if len(res.Teams) > int(query.Pagination.Limit)-1 { @@ -170,7 +181,7 @@ func (s *legacySQLStore) ListTeams(ctx context.Context, ns claims.NamespaceInfo, } if query.UID == "" { - res.RV, err = sql.GetResourceVersion(ctx, "team", "updated") + res.RV, err = sqlConn.GetResourceVersion(ctx, "team", "updated") } return res, err diff --git a/pkg/tests/apis/iam/team_integration_test.go b/pkg/tests/apis/iam/team_integration_test.go index e8bb115dfb7..16d27456e03 100644 --- a/pkg/tests/apis/iam/team_integration_test.go +++ b/pkg/tests/apis/iam/team_integration_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "testing" + "time" "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/api/errors" @@ -222,6 +223,36 @@ func doTeamCRUDTestsUsingTheNewAPIs(t *testing.T, helper *apis.K8sTestHelper) { require.Equal(t, createdUID, fetched.GetName()) require.Equal(t, "default", fetched.GetNamespace()) + + // Cleanup + err = teamClient.Resource.Delete(ctx, createdUID, metav1.DeleteOptions{}) + require.NoError(t, err) + }) + + t.Run("should list teams correctly", func(t *testing.T) { + ctx := context.Background() + + teamClient := helper.GetResourceClient(apis.ResourceClientArgs{ + User: helper.Org1.Admin, + Namespace: helper.Namespacer(helper.Org1.Admin.Identity.GetOrgID()), + GVR: gvrTeams, + }) + + // For ensuring that it is able to list a team which has external_uid = null and is_provisioned = null + // only matters when legacy storage is involved + env := helper.GetEnv() + res, err := env.SQLStore.GetSqlxSession().Exec(ctx, "INSERT INTO team (org_id, uid, name, email, is_provisioned, external_uid, created, updated) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", + helper.Org1.Admin.Identity.GetOrgID(), "t000000001", "List Team 1", "list-team-1@example.com", nil, nil, time.Now(), time.Now()) + require.NoError(t, err) + require.NotNil(t, res) + + list, err := teamClient.Resource.List(ctx, metav1.ListOptions{}) + require.NoError(t, err) + require.NotNil(t, list) + + // Cleanup + _, err = env.SQLStore.GetSqlxSession().Exec(ctx, "DELETE FROM team WHERE uid = ?", "t000000001") + require.NoError(t, err) }) }