Skip to content

Commit 446fc24

Browse files
committed
Convert static host user to new cache mechanism
Moves static host users to the new cache collection scheme that was introduced in #52210. No additional functionality changes have been made here. This should be a purely mechanical translation to the new internal caching machinery.
1 parent 97273eb commit 446fc24

File tree

6 files changed

+177
-125
lines changed

6 files changed

+177
-125
lines changed

lib/cache/cache.go

-35
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ import (
4545
identitycenterv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/identitycenter/v1"
4646
kubewaitingcontainerpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1"
4747
provisioningv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/provisioning/v1"
48-
userprovisioningpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v2"
4948
usertasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1"
5049
"github.com/gravitational/teleport/api/internalutils/stream"
5150
apitracing "github.com/gravitational/teleport/api/observability/tracing"
@@ -527,7 +526,6 @@ type Cache struct {
527526
lowVolumeEventsFanout *utils.RoundRobin[*services.FanoutV2]
528527
kubeWaitingContsCache *local.KubeWaitingContainerService
529528
accessMontoringRuleCache services.AccessMonitoringRules
530-
staticHostUsersCache *local.StaticHostUserService
531529
provisioningStatesCache *local.ProvisioningStateService
532530
identityCenterCache *local.IdentityCenterService
533531
pluginStaticCredentialsCache *local.PluginStaticCredentialsService
@@ -995,12 +993,6 @@ func New(config Config) (*Cache, error) {
995993
return nil, trace.Wrap(err)
996994
}
997995

998-
staticHostUserCache, err := local.NewStaticHostUserService(config.Backend)
999-
if err != nil {
1000-
cancel()
1001-
return nil, trace.Wrap(err)
1002-
}
1003-
1004996
identityService, err := local.NewIdentityService(config.Backend)
1005997
if err != nil {
1006998
cancel()
@@ -1067,7 +1059,6 @@ func New(config Config) (*Cache, error) {
10671059
eventsFanout: fanout,
10681060
lowVolumeEventsFanout: utils.NewRoundRobin(lowVolumeFanouts),
10691061
kubeWaitingContsCache: kubeWaitingContsCache,
1070-
staticHostUsersCache: staticHostUserCache,
10711062
provisioningStatesCache: provisioningStatesCache,
10721063
identityCenterCache: identityCenterCache,
10731064
pluginStaticCredentialsCache: pluginStaticCredentialsCache,
@@ -1898,32 +1889,6 @@ func (c *Cache) GetKubernetesWaitingContainer(ctx context.Context, req *kubewait
18981889
return rg.reader.GetKubernetesWaitingContainer(ctx, req)
18991890
}
19001891

1901-
// ListStaticHostUsers lists static host users.
1902-
func (c *Cache) ListStaticHostUsers(ctx context.Context, pageSize int, pageToken string) ([]*userprovisioningpb.StaticHostUser, string, error) {
1903-
ctx, span := c.Tracer.Start(ctx, "cache/ListStaticHostUsers")
1904-
defer span.End()
1905-
1906-
rg, err := readLegacyCollectionCache(c, c.legacyCacheCollections.staticHostUsers)
1907-
if err != nil {
1908-
return nil, "", trace.Wrap(err)
1909-
}
1910-
defer rg.Release()
1911-
return rg.reader.ListStaticHostUsers(ctx, pageSize, pageToken)
1912-
}
1913-
1914-
// GetStaticHostUser returns a static host user by name.
1915-
func (c *Cache) GetStaticHostUser(ctx context.Context, name string) (*userprovisioningpb.StaticHostUser, error) {
1916-
ctx, span := c.Tracer.Start(ctx, "cache/GetStaticHostUser")
1917-
defer span.End()
1918-
1919-
rg, err := readLegacyCollectionCache(c, c.legacyCacheCollections.staticHostUsers)
1920-
if err != nil {
1921-
return nil, trace.Wrap(err)
1922-
}
1923-
defer rg.Release()
1924-
return rg.reader.GetStaticHostUser(ctx, name)
1925-
}
1926-
19271892
func (c *Cache) GetDatabaseObject(ctx context.Context, name string) (*dbobjectv1.DatabaseObject, error) {
19281893
ctx, span := c.Tracer.Start(ctx, "cache/GetDatabaseObject")
19291894
defer span.End()

lib/cache/cache_test.go

+1-29
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ type testPack struct {
141141
crownJewels services.CrownJewels
142142
databaseObjects services.DatabaseObjects
143143
spiffeFederations *local.SPIFFEFederationService
144-
staticHostUsers services.StaticHostUser
144+
staticHostUsers *local.StaticHostUserService
145145
autoUpdateService services.AutoUpdateService
146146
provisioningStates services.ProvisioningStates
147147
identityCenter services.IdentityCenter
@@ -1688,34 +1688,6 @@ func TestDatabaseObjects(t *testing.T) {
16881688
})
16891689
}
16901690

1691-
// TestStaticHostUsers tests that CRUD operations on static host user resources are
1692-
// replicated from the backend to the cache.
1693-
func TestStaticHostUsers(t *testing.T) {
1694-
t.Parallel()
1695-
1696-
p := newTestPack(t, ForAuth)
1697-
t.Cleanup(p.Close)
1698-
1699-
testResources153(t, p, testFuncs153[*userprovisioningpb.StaticHostUser]{
1700-
newResource: func(name string) (*userprovisioningpb.StaticHostUser, error) {
1701-
return newStaticHostUser(t, name), nil
1702-
},
1703-
create: func(ctx context.Context, item *userprovisioningpb.StaticHostUser) error {
1704-
_, err := p.staticHostUsers.CreateStaticHostUser(ctx, item)
1705-
return trace.Wrap(err)
1706-
},
1707-
list: func(ctx context.Context) ([]*userprovisioningpb.StaticHostUser, error) {
1708-
items, _, err := p.staticHostUsers.ListStaticHostUsers(ctx, 0, "")
1709-
return items, trace.Wrap(err)
1710-
},
1711-
cacheList: func(ctx context.Context) ([]*userprovisioningpb.StaticHostUser, error) {
1712-
items, _, err := p.cache.ListStaticHostUsers(ctx, 0, "")
1713-
return items, trace.Wrap(err)
1714-
},
1715-
deleteAll: p.cache.staticHostUsersCache.DeleteAllStaticHostUsers,
1716-
})
1717-
}
1718-
17191691
// testResources is a generic tester for resources.
17201692
func testResources[T types.Resource](t *testing.T, p *testPack, funcs testFuncs[T]) {
17211693
ctx := context.Background()

lib/cache/collections.go

+10
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
identitycenterv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/identitycenter/v1"
2727
machineidv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/machineid/v1"
2828
notificationsv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/notifications/v1"
29+
userprovisioningv2 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v2"
2930
workloadidentityv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/workloadidentity/v1"
3031
"github.com/gravitational/teleport/api/types"
3132
)
@@ -98,6 +99,7 @@ type collections struct {
9899
locks *collection[types.Lock, lockIndex]
99100
tunnelConnections *collection[types.TunnelConnection, tunnelConnectionIndex]
100101
remoteClusters *collection[types.RemoteCluster, remoteClusterIndex]
102+
staticHostUsers *collection[*userprovisioningv2.StaticHostUser, staticHostUserIndex]
101103
}
102104

103105
// setupCollections ensures that the appropriate [collection] is
@@ -467,6 +469,14 @@ func setupCollections(c Config) (*collections, error) {
467469

468470
out.remoteClusters = collect
469471
out.byKind[resourceKind] = out.remoteClusters
472+
case types.KindStaticHostUser:
473+
collect, err := newStaticHostUserCollection(c.StaticHostUsers, watch)
474+
if err != nil {
475+
return nil, trace.Wrap(err)
476+
}
477+
478+
out.staticHostUsers = collect
479+
out.byKind[resourceKind] = out.staticHostUsers
470480
}
471481
}
472482

lib/cache/legacy_collections.go

-61
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ import (
3333
identitycenterv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/identitycenter/v1"
3434
kubewaitingcontainerpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1"
3535
provisioningv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/provisioning/v1"
36-
userprovisioningpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v2"
3736
userspb "github.com/gravitational/teleport/api/gen/proto/go/teleport/users/v1"
3837
usertasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1"
3938
"github.com/gravitational/teleport/api/types"
@@ -118,7 +117,6 @@ type legacyCollections struct {
118117
userTasks collectionReader[userTasksGetter]
119118
crownJewels collectionReader[crownjewelsGetter]
120119
kubeWaitingContainers collectionReader[kubernetesWaitingContainerGetter]
121-
staticHostUsers collectionReader[staticHostUserGetter]
122120
networkRestrictions collectionReader[networkRestrictionGetter]
123121
proxies collectionReader[services.ProxyGetter]
124122
uiConfigs collectionReader[uiConfigGetter]
@@ -288,15 +286,6 @@ func setupLegacyCollections(c *Cache, watches []types.WatchKind) (*legacyCollect
288286
watch: watch,
289287
}
290288
collections.byKind[resourceKind] = collections.kubeWaitingContainers
291-
case types.KindStaticHostUser:
292-
if c.StaticHostUsers == nil {
293-
return nil, trace.BadParameter("missing parameter StaticHostUsers")
294-
}
295-
collections.staticHostUsers = &genericCollection[*userprovisioningpb.StaticHostUser, staticHostUserGetter, staticHostUserExecutor]{
296-
cache: c,
297-
watch: watch,
298-
}
299-
collections.byKind[resourceKind] = collections.staticHostUsers
300289
case types.KindAccessMonitoringRule:
301290
if c.AccessMonitoringRules == nil {
302291
return nil, trace.BadParameter("missing parameter AccessMonitoringRule")
@@ -776,56 +765,6 @@ type kubernetesWaitingContainerGetter interface {
776765

777766
var _ executor[*kubewaitingcontainerpb.KubernetesWaitingContainer, kubernetesWaitingContainerGetter] = kubeWaitingContainerExecutor{}
778767

779-
type staticHostUserExecutor struct{}
780-
781-
func (staticHostUserExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]*userprovisioningpb.StaticHostUser, error) {
782-
var (
783-
startKey string
784-
allUsers []*userprovisioningpb.StaticHostUser
785-
)
786-
for {
787-
users, nextKey, err := cache.StaticHostUsers.ListStaticHostUsers(ctx, 0, startKey)
788-
if err != nil {
789-
return nil, trace.Wrap(err)
790-
}
791-
792-
allUsers = append(allUsers, users...)
793-
794-
if nextKey == "" {
795-
break
796-
}
797-
startKey = nextKey
798-
}
799-
return allUsers, nil
800-
}
801-
802-
func (staticHostUserExecutor) upsert(ctx context.Context, cache *Cache, resource *userprovisioningpb.StaticHostUser) error {
803-
_, err := cache.staticHostUsersCache.UpsertStaticHostUser(ctx, resource)
804-
return trace.Wrap(err)
805-
}
806-
807-
func (staticHostUserExecutor) deleteAll(ctx context.Context, cache *Cache) error {
808-
return trace.Wrap(cache.staticHostUsersCache.DeleteAllStaticHostUsers(ctx))
809-
}
810-
811-
func (staticHostUserExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
812-
return trace.Wrap(cache.staticHostUsersCache.DeleteStaticHostUser(ctx, resource.GetName()))
813-
}
814-
815-
func (staticHostUserExecutor) isSingleton() bool { return false }
816-
817-
func (staticHostUserExecutor) getReader(cache *Cache, cacheOK bool) staticHostUserGetter {
818-
if cacheOK {
819-
return cache.staticHostUsersCache
820-
}
821-
return cache.Config.StaticHostUsers
822-
}
823-
824-
type staticHostUserGetter interface {
825-
ListStaticHostUsers(ctx context.Context, pageSize int, pageToken string) ([]*userprovisioningpb.StaticHostUser, string, error)
826-
GetStaticHostUser(ctx context.Context, name string) (*userprovisioningpb.StaticHostUser, error)
827-
}
828-
829768
type crownJewelsExecutor struct{}
830769

831770
func (crownJewelsExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]*crownjewelv1.CrownJewel, error) {

lib/cache/static_host_user.go

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Teleport
2+
// Copyright (C) 2025 Gravitational, Inc.
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package cache
18+
19+
import (
20+
"context"
21+
22+
"github.com/gravitational/trace"
23+
24+
headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1"
25+
userprovisioningv2 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v2"
26+
"github.com/gravitational/teleport/api/types"
27+
"github.com/gravitational/teleport/api/utils"
28+
"github.com/gravitational/teleport/lib/services"
29+
)
30+
31+
type staticHostUserIndex string
32+
33+
const staticHostUserNameIndex staticHostUserIndex = "name"
34+
35+
func newStaticHostUserCollection(upstream services.StaticHostUser, w types.WatchKind) (*collection[*userprovisioningv2.StaticHostUser, staticHostUserIndex], error) {
36+
if upstream == nil {
37+
return nil, trace.BadParameter("missing parameter StaticHostUser")
38+
}
39+
40+
return &collection[*userprovisioningv2.StaticHostUser, staticHostUserIndex]{
41+
store: newStore(map[staticHostUserIndex]func(*userprovisioningv2.StaticHostUser) string{
42+
staticHostUserNameIndex: func(shu *userprovisioningv2.StaticHostUser) string {
43+
return shu.GetMetadata().GetName()
44+
},
45+
}),
46+
fetcher: func(ctx context.Context, loadSecrets bool) ([]*userprovisioningv2.StaticHostUser, error) {
47+
var startKey string
48+
var allUsers []*userprovisioningv2.StaticHostUser
49+
50+
for {
51+
users, nextKey, err := upstream.ListStaticHostUsers(ctx, 0, startKey)
52+
if err != nil {
53+
return nil, trace.Wrap(err)
54+
}
55+
56+
allUsers = append(allUsers, users...)
57+
58+
if nextKey == "" {
59+
break
60+
}
61+
startKey = nextKey
62+
}
63+
return allUsers, nil
64+
},
65+
headerTransform: func(hdr *types.ResourceHeader) *userprovisioningv2.StaticHostUser {
66+
return &userprovisioningv2.StaticHostUser{
67+
Kind: hdr.Kind,
68+
Version: hdr.Version,
69+
Metadata: &headerv1.Metadata{
70+
Name: hdr.Metadata.Name,
71+
},
72+
}
73+
},
74+
watch: w,
75+
}, nil
76+
}
77+
78+
// ListStaticHostUsers lists static host users.
79+
func (c *Cache) ListStaticHostUsers(ctx context.Context, pageSize int, pageToken string) ([]*userprovisioningv2.StaticHostUser, string, error) {
80+
ctx, span := c.Tracer.Start(ctx, "cache/ListStaticHostUsers")
81+
defer span.End()
82+
83+
lister := genericLister[*userprovisioningv2.StaticHostUser, staticHostUserIndex]{
84+
cache: c,
85+
collection: c.collections.staticHostUsers,
86+
index: staticHostUserNameIndex,
87+
upstreamList: c.Config.StaticHostUsers.ListStaticHostUsers,
88+
nextToken: func(t *userprovisioningv2.StaticHostUser) string {
89+
return t.GetMetadata().GetName()
90+
},
91+
clone: utils.CloneProtoMsg[*userprovisioningv2.StaticHostUser],
92+
}
93+
out, next, err := lister.list(ctx, pageSize, pageToken)
94+
return out, next, trace.Wrap(err)
95+
}
96+
97+
// GetStaticHostUser returns a static host user by name.
98+
func (c *Cache) GetStaticHostUser(ctx context.Context, name string) (*userprovisioningv2.StaticHostUser, error) {
99+
ctx, span := c.Tracer.Start(ctx, "cache/GetStaticHostUser")
100+
defer span.End()
101+
102+
getter := genericGetter[*userprovisioningv2.StaticHostUser, staticHostUserIndex]{
103+
cache: c,
104+
collection: c.collections.staticHostUsers,
105+
index: staticHostUserNameIndex,
106+
upstreamGet: c.Config.StaticHostUsers.GetStaticHostUser,
107+
clone: utils.CloneProtoMsg[*userprovisioningv2.StaticHostUser],
108+
}
109+
out, err := getter.get(ctx, name)
110+
return out, trace.Wrap(err)
111+
}

0 commit comments

Comments
 (0)