diff --git a/api/client/client.go b/api/client/client.go
index c9a89cfdf820e..003a69637d728 100644
--- a/api/client/client.go
+++ b/api/client/client.go
@@ -55,6 +55,7 @@ import (
"github.com/gravitational/teleport/api/client/discoveryconfig"
"github.com/gravitational/teleport/api/client/dynamicwindows"
"github.com/gravitational/teleport/api/client/externalauditstorage"
+ gitserverclient "github.com/gravitational/teleport/api/client/gitserver"
kubewaitingcontainerclient "github.com/gravitational/teleport/api/client/kubewaitingcontainer"
"github.com/gravitational/teleport/api/client/okta"
"github.com/gravitational/teleport/api/client/proto"
@@ -77,7 +78,7 @@ import (
discoveryconfigv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/discoveryconfig/v1"
dynamicwindowsv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/dynamicwindows/v1"
externalauditstoragev1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/externalauditstorage/v1"
- gitserverv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/gitserver/v1"
+ gitserverpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/gitserver/v1"
identitycenterv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/identitycenter/v1"
integrationpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/integration/v1"
kubeproto "github.com/gravitational/teleport/api/gen/proto/go/teleport/kube/v1"
@@ -4876,8 +4877,8 @@ func (c *Client) UserTasksServiceClient() *usertaskapi.Client {
}
// GitServerClient returns a client for managing git servers
-func (c *Client) GitServerClient() gitserverv1.GitServerServiceClient {
- return gitserverv1.NewGitServerServiceClient(c.conn)
+func (c *Client) GitServerClient() *gitserverclient.Client {
+ return gitserverclient.NewClient(gitserverpb.NewGitServerServiceClient(c.conn))
}
// GetCertAuthority retrieves a CA by type and domain.
diff --git a/api/client/gitserver/gitserver.go b/api/client/gitserver/gitserver.go
new file mode 100644
index 0000000000000..70c69aa73dc75
--- /dev/null
+++ b/api/client/gitserver/gitserver.go
@@ -0,0 +1,125 @@
+// Copyright 2024 Gravitational, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package gitserver
+
+import (
+ "context"
+
+ "github.com/gravitational/trace"
+
+ gitserverv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/gitserver/v1"
+ "github.com/gravitational/teleport/api/types"
+)
+
+// Client is an Git servers client.
+type Client struct {
+ grpcClient gitserverv1.GitServerServiceClient
+}
+
+// NewClient creates a new Git servers client.
+func NewClient(grpcClient gitserverv1.GitServerServiceClient) *Client {
+ return &Client{
+ grpcClient: grpcClient,
+ }
+}
+
+// GetGitServer returns Git servers by name.
+func (c *Client) GetGitServer(ctx context.Context, name string) (types.Server, error) {
+ server, err := c.grpcClient.GetGitServer(ctx, &gitserverv1.GetGitServerRequest{Name: name})
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+ return server, nil
+}
+
+// ListGitServers returns all Git servers matching filter.
+func (c *Client) ListGitServers(ctx context.Context, pageSize int, pageToken string) ([]types.Server, string, error) {
+ resp, err := c.grpcClient.ListGitServers(ctx, &gitserverv1.ListGitServersRequest{
+ PageSize: int32(pageSize),
+ PageToken: pageToken,
+ })
+ if err != nil {
+ return nil, "", trace.Wrap(err)
+ }
+
+ servers := make([]types.Server, 0, len(resp.Servers))
+ for _, server := range resp.Servers {
+ servers = append(servers, server)
+ }
+ return servers, resp.NextPageToken, nil
+}
+
+func toServerV2(server types.Server) (*types.ServerV2, error) {
+ serverV2, ok := server.(*types.ServerV2)
+ if !ok {
+ return nil, trace.Errorf("encountered unexpected server type: %T", serverV2)
+ }
+ return serverV2, nil
+}
+
+// CreateGitServer creates a Git server resource.
+func (c *Client) CreateGitServer(ctx context.Context, item types.Server) (types.Server, error) {
+ serverV2, err := toServerV2(item)
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+ resp, err := c.grpcClient.CreateGitServer(ctx, &gitserverv1.CreateGitServerRequest{
+ Server: serverV2,
+ })
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+ return resp, nil
+}
+
+// UpdateGitServer updates a Git server resource.
+func (c *Client) UpdateGitServer(ctx context.Context, item types.Server) (types.Server, error) {
+ serverV2, err := toServerV2(item)
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+ resp, err := c.grpcClient.UpdateGitServer(ctx, &gitserverv1.UpdateGitServerRequest{
+ Server: serverV2,
+ })
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+ return resp, nil
+}
+
+// UpsertGitServer updates a Git server resource, creating it if it doesn't exist.
+func (c *Client) UpsertGitServer(ctx context.Context, item types.Server) (types.Server, error) {
+ serverV2, err := toServerV2(item)
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+ resp, err := c.grpcClient.UpsertGitServer(ctx, &gitserverv1.UpsertGitServerRequest{
+ Server: serverV2,
+ })
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+ return resp, nil
+}
+
+// DeleteGitServer removes the specified Git server resource.
+func (c *Client) DeleteGitServer(ctx context.Context, name string) error {
+ _, err := c.grpcClient.DeleteGitServer(ctx, &gitserverv1.DeleteGitServerRequest{Name: name})
+ return trace.Wrap(err)
+}
+
+// DeleteAllGitServers removes all Git server resources.
+func (c *Client) DeleteAllGitServers(ctx context.Context) error {
+ return trace.NotImplemented("DeleteAllGitServers servers not implemented")
+}
diff --git a/lib/auth/accesspoint/accesspoint.go b/lib/auth/accesspoint/accesspoint.go
index ab66082d3ef17..d078d25d87b92 100644
--- a/lib/auth/accesspoint/accesspoint.go
+++ b/lib/auth/accesspoint/accesspoint.go
@@ -109,6 +109,7 @@ type Config struct {
ProvisioningStates services.ProvisioningStates
IdentityCenter services.IdentityCenter
PluginStaticCredentials services.PluginStaticCredentials
+ GitServers services.GitServers
}
func (c *Config) CheckAndSetDefaults() error {
@@ -207,6 +208,7 @@ func NewCache(cfg Config) (*cache.Cache, error) {
ProvisioningStates: cfg.ProvisioningStates,
IdentityCenter: cfg.IdentityCenter,
PluginStaticCredentials: cfg.PluginStaticCredentials,
+ GitServers: cfg.GitServers,
}
return cache.New(cfg.Setup(cacheCfg))
diff --git a/lib/auth/authclient/clt.go b/lib/auth/authclient/clt.go
index caf56cf3b6e09..4217b12a5991e 100644
--- a/lib/auth/authclient/clt.go
+++ b/lib/auth/authclient/clt.go
@@ -35,6 +35,7 @@ import (
"github.com/gravitational/teleport/api/client/databaseobject"
"github.com/gravitational/teleport/api/client/dynamicwindows"
"github.com/gravitational/teleport/api/client/externalauditstorage"
+ "github.com/gravitational/teleport/api/client/gitserver"
"github.com/gravitational/teleport/api/client/proto"
"github.com/gravitational/teleport/api/client/secreport"
"github.com/gravitational/teleport/api/client/usertask"
@@ -43,7 +44,6 @@ import (
clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1"
dbobjectimportrulev1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/dbobjectimportrule/v1"
devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1"
- gitserverv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/gitserver/v1"
identitycenterv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/identitycenter/v1"
integrationv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/integration/v1"
loginrulepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/loginrule/v1"
@@ -1896,5 +1896,5 @@ type ClientI interface {
IntegrationsClient() integrationv1.IntegrationServiceClient
// GitServerClient returns git server client.
- GitServerClient() gitserverv1.GitServerServiceClient
+ GitServerClient() *gitserver.Client
}
diff --git a/lib/auth/helpers.go b/lib/auth/helpers.go
index b13301ca4f76f..71804b4ca0049 100644
--- a/lib/auth/helpers.go
+++ b/lib/auth/helpers.go
@@ -371,6 +371,7 @@ func NewTestAuthServer(cfg TestAuthServerConfig) (*TestAuthServer, error) {
WindowsDesktops: svces.WindowsDesktops,
DynamicWindowsDesktops: svces.DynamicWindowsDesktops,
PluginStaticCredentials: svces.PluginStaticCredentials,
+ GitServers: svces.GitServers,
})
if err != nil {
return nil, trace.Wrap(err)
diff --git a/lib/cache/cache.go b/lib/cache/cache.go
index de46c13323831..fcb2a3bf7da5f 100644
--- a/lib/cache/cache.go
+++ b/lib/cache/cache.go
@@ -103,6 +103,7 @@ var highVolumeResources = map[string]struct{}{
types.KindWindowsDesktopService: {},
types.KindKubeServer: {},
types.KindDatabaseObject: {},
+ types.KindGitServer: {},
}
func isHighVolumeResource(kind string) bool {
@@ -199,6 +200,7 @@ func ForAuth(cfg Config) Config {
{Kind: types.KindIdentityCenterPrincipalAssignment},
{Kind: types.KindIdentityCenterAccountAssignment},
{Kind: types.KindPluginStaticCredentials},
+ {Kind: types.KindGitServer},
}
cfg.QueueSize = defaults.AuthQueueSize
// We don't want to enable partial health for auth cache because auth uses an event stream
@@ -256,6 +258,7 @@ func ForProxy(cfg Config) Config {
{Kind: types.KindAutoUpdateVersion},
{Kind: types.KindAutoUpdateAgentRollout},
{Kind: types.KindUserTask},
+ {Kind: types.KindGitServer},
}
cfg.QueueSize = defaults.ProxyQueueSize
return cfg
@@ -552,6 +555,7 @@ type Cache struct {
provisioningStatesCache *local.ProvisioningStateService
identityCenterCache *local.IdentityCenterService
pluginStaticCredentialsCache *local.PluginStaticCredentialsService
+ gitServersCache *local.GitServerService
// closed indicates that the cache has been closed
closed atomic.Bool
@@ -788,6 +792,8 @@ type Config struct {
IdentityCenter services.IdentityCenter
// PluginStaticCredentials is the plugin static credentials services
PluginStaticCredentials services.PluginStaticCredentials
+ // GitServers is the Git server service.
+ GitServers services.GitServerGetter
}
// CheckAndSetDefaults checks parameters and sets default values
@@ -1033,6 +1039,12 @@ func New(config Config) (*Cache, error) {
return nil, trace.Wrap(err)
}
+ gitServersCache, err := local.NewGitServerService(config.Backend)
+ if err != nil {
+ cancel()
+ return nil, trace.Wrap(err)
+ }
+
cs := &Cache{
ctx: ctx,
cancel: cancel,
@@ -1081,6 +1093,7 @@ func New(config Config) (*Cache, error) {
provisioningStatesCache: provisioningStatesCache,
identityCenterCache: identityCenterCache,
pluginStaticCredentialsCache: pluginStaticCredentialsCache,
+ gitServersCache: gitServersCache,
Logger: log.WithFields(log.Fields{
teleport.ComponentKey: config.Component,
}),
diff --git a/lib/cache/cache_test.go b/lib/cache/cache_test.go
index e49baa304aad8..af4b4d195bce4 100644
--- a/lib/cache/cache_test.go
+++ b/lib/cache/cache_test.go
@@ -142,6 +142,7 @@ type testPack struct {
provisioningStates services.ProvisioningStates
identityCenter services.IdentityCenter
pluginStaticCredentials *local.PluginStaticCredentialsService
+ gitServers services.GitServers
}
// testFuncs are functions to support testing an object in a cache.
@@ -409,6 +410,11 @@ func newPackWithoutCache(dir string, opts ...packOption) (*testPack, error) {
return nil, trace.Wrap(err)
}
+ p.gitServers, err = local.NewGitServerService(p.backend)
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+
return p, nil
}
@@ -463,6 +469,7 @@ func newPack(dir string, setupConfig func(c Config) Config, opts ...packOption)
ProvisioningStates: p.provisioningStates,
IdentityCenter: p.identityCenter,
PluginStaticCredentials: p.pluginStaticCredentials,
+ GitServers: p.gitServers,
MaxRetryPeriod: 200 * time.Millisecond,
EventsC: p.eventsC,
}))
@@ -878,6 +885,7 @@ func TestCompletenessInit(t *testing.T) {
IdentityCenter: p.identityCenter,
PluginStaticCredentials: p.pluginStaticCredentials,
EventsC: p.eventsC,
+ GitServers: p.gitServers,
}))
require.NoError(t, err)
@@ -963,6 +971,7 @@ func TestCompletenessReset(t *testing.T) {
PluginStaticCredentials: p.pluginStaticCredentials,
MaxRetryPeriod: 200 * time.Millisecond,
EventsC: p.eventsC,
+ GitServers: p.gitServers,
}))
require.NoError(t, err)
@@ -1175,6 +1184,7 @@ func TestListResources_NodesTTLVariant(t *testing.T) {
MaxRetryPeriod: 200 * time.Millisecond,
EventsC: p.eventsC,
neverOK: true, // ensure reads are never healthy
+ GitServers: p.gitServers,
}))
require.NoError(t, err)
@@ -1270,6 +1280,7 @@ func initStrategy(t *testing.T) {
PluginStaticCredentials: p.pluginStaticCredentials,
MaxRetryPeriod: 200 * time.Millisecond,
EventsC: p.eventsC,
+ GitServers: p.gitServers,
}))
require.NoError(t, err)
@@ -3544,6 +3555,7 @@ func TestCacheWatchKindExistsInEvents(t *testing.T) {
types.KindIdentityCenterAccountAssignment: types.Resource153ToLegacy(newIdentityCenterAccountAssignment("some_account_assignment")),
types.KindIdentityCenterPrincipalAssignment: types.Resource153ToLegacy(newIdentityCenterPrincipalAssignment("some_principal_assignment")),
types.KindPluginStaticCredentials: &types.PluginStaticCredentialsV1{},
+ types.KindGitServer: &types.ServerV2{},
}
for name, cfg := range cases {
diff --git a/lib/cache/collections.go b/lib/cache/collections.go
index 36aaefebf5398..2635a0d71ea04 100644
--- a/lib/cache/collections.go
+++ b/lib/cache/collections.go
@@ -177,6 +177,7 @@ type cacheCollections struct {
identityCenterPrincipalAssignments collectionReader[identityCenterPrincipalAssignmentGetter]
identityCenterAccountAssignments collectionReader[identityCenterAccountAssignmentGetter]
pluginStaticCredentials collectionReader[pluginStaticCredentialsGetter]
+ gitServers collectionReader[services.GitServerGetter]
}
// setupCollections returns a registry of collections.
@@ -799,6 +800,19 @@ func setupCollections(c *Cache, watches []types.WatchKind) (*cacheCollections, e
}
collections.byKind[resourceKind] = collections.pluginStaticCredentials
+ case types.KindGitServer:
+ if c.GitServers == nil {
+ return nil, trace.BadParameter("missing parameter GitServers")
+ }
+ collections.gitServers = &genericCollection[
+ types.Server,
+ services.GitServerGetter,
+ gitServerExecutor,
+ ]{
+ cache: c,
+ watch: watch,
+ }
+ collections.byKind[resourceKind] = collections.gitServers
default:
return nil, trace.BadParameter("resource %q is not supported", watch.Kind)
}
diff --git a/lib/cache/git_server.go b/lib/cache/git_server.go
new file mode 100644
index 0000000000000..849a160757eee
--- /dev/null
+++ b/lib/cache/git_server.go
@@ -0,0 +1,95 @@
+/*
+ * Teleport
+ * Copyright (C) 2024 Gravitational, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package cache
+
+import (
+ "context"
+
+ "github.com/gravitational/trace"
+
+ apidefaults "github.com/gravitational/teleport/api/defaults"
+ "github.com/gravitational/teleport/api/types"
+ "github.com/gravitational/teleport/lib/services"
+)
+
+func (c *Cache) GetGitServer(ctx context.Context, name string) (types.Server, error) {
+ ctx, span := c.Tracer.Start(ctx, "cache/GetGitServer")
+ defer span.End()
+
+ rg, err := readCollectionCache(c, c.collections.gitServers)
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+ defer rg.Release()
+ return rg.reader.GetGitServer(ctx, name)
+}
+
+func (c *Cache) ListGitServers(ctx context.Context, pageSize int, pageToken string) ([]types.Server, string, error) {
+ ctx, span := c.Tracer.Start(ctx, "cache/ListGitServers")
+ defer span.End()
+
+ rg, err := readCollectionCache(c, c.collections.gitServers)
+ if err != nil {
+ return nil, "", trace.Wrap(err)
+ }
+ defer rg.Release()
+ return rg.reader.ListGitServers(ctx, pageSize, pageToken)
+}
+
+type gitServerExecutor struct{}
+
+func (gitServerExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) (all []types.Server, err error) {
+ var page []types.Server
+ var nextToken string
+ for {
+ page, nextToken, err = cache.GitServers.ListGitServers(ctx, apidefaults.DefaultChunkSize, nextToken)
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+ all = append(all, page...)
+ if nextToken == "" {
+ break
+ }
+ }
+ return all, nil
+}
+
+func (gitServerExecutor) upsert(ctx context.Context, cache *Cache, resource types.Server) error {
+ _, err := cache.gitServersCache.UpsertGitServer(ctx, resource)
+ return trace.Wrap(err)
+}
+
+func (gitServerExecutor) deleteAll(ctx context.Context, cache *Cache) error {
+ return cache.gitServersCache.DeleteAllGitServers(ctx)
+}
+
+func (gitServerExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
+ return cache.gitServersCache.DeleteGitServer(ctx, resource.GetName())
+}
+
+func (gitServerExecutor) isSingleton() bool { return false }
+
+func (gitServerExecutor) getReader(cache *Cache, cacheOK bool) services.GitServerGetter {
+ if cacheOK {
+ return cache.gitServersCache
+ }
+ return cache.Config.GitServers
+}
+
+var _ executor[types.Server, services.GitServerGetter] = gitServerExecutor{}
diff --git a/lib/cache/git_server_test.go b/lib/cache/git_server_test.go
new file mode 100644
index 0000000000000..35ce40941a53b
--- /dev/null
+++ b/lib/cache/git_server_test.go
@@ -0,0 +1,65 @@
+/*
+ * Teleport
+ * Copyright (C) 2024 Gravitational, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package cache
+
+import (
+ "context"
+ "testing"
+
+ "github.com/gravitational/trace"
+ "github.com/stretchr/testify/require"
+
+ "github.com/gravitational/teleport/api/types"
+)
+
+func TestGitServers(t *testing.T) {
+ t.Parallel()
+
+ p, err := newPack(t.TempDir(), ForAuth)
+ require.NoError(t, err)
+ t.Cleanup(p.Close)
+
+ testResources(t, p, testFuncs[types.Server]{
+ newResource: func(name string) (types.Server, error) {
+ return types.NewGitHubServer(
+ types.GitHubServerMetadata{
+ Integration: name,
+ Organization: name,
+ })
+ },
+ create: func(ctx context.Context, server types.Server) error {
+ _, err := p.gitServers.CreateGitServer(ctx, server)
+ return trace.Wrap(err)
+ },
+ list: func(ctx context.Context) ([]types.Server, error) {
+ servers, _, err := p.gitServers.ListGitServers(ctx, 0, "")
+ return servers, trace.Wrap(err)
+ },
+ update: func(ctx context.Context, server types.Server) error {
+ _, err := p.gitServers.UpdateGitServer(ctx, server)
+ return trace.Wrap(err)
+ },
+ deleteAll: p.gitServers.DeleteAllGitServers,
+ cacheList: func(ctx context.Context) ([]types.Server, error) {
+ servers, _, err := p.cache.ListGitServers(ctx, 0, "")
+ return servers, trace.Wrap(err)
+ },
+ cacheGet: p.cache.GetGitServer,
+ })
+}
diff --git a/lib/service/service.go b/lib/service/service.go
index d1e92c40675dc..9855dd6def1c9 100644
--- a/lib/service/service.go
+++ b/lib/service/service.go
@@ -2553,6 +2553,7 @@ func (process *TeleportProcess) newAccessCacheForServices(cfg accesspoint.Config
cfg.ProvisioningStates = services.ProvisioningStates
cfg.IdentityCenter = services.IdentityCenter
cfg.PluginStaticCredentials = services.PluginStaticCredentials
+ cfg.GitServers = services.GitServers
return accesspoint.NewCache(cfg)
}
@@ -2599,6 +2600,7 @@ func (process *TeleportProcess) newAccessCacheForClient(cfg accesspoint.Config,
cfg.WindowsDesktops = client
cfg.DynamicWindowsDesktops = client.DynamicDesktopClient()
cfg.AutoUpdateService = client
+ cfg.GitServers = client.GitServerClient()
return accesspoint.NewCache(cfg)
}
diff --git a/lib/services/local/events.go b/lib/services/local/events.go
index 9a63b3fea4f9e..d0522bf7bd5f2 100644
--- a/lib/services/local/events.go
+++ b/lib/services/local/events.go
@@ -250,6 +250,8 @@ func (e *EventsService) NewWatcher(ctx context.Context, watch types.Watch) (type
parser = newIdentityCenterAccountAssignmentParser()
case types.KindPluginStaticCredentials:
parser = newPluginStaticCredentialsParser()
+ case types.KindGitServer:
+ parser = newGitServerParser()
default:
if watch.AllowPartialSuccess {
continue
diff --git a/lib/services/local/git_server.go b/lib/services/local/git_server.go
index 2d7d7c58b3263..857bc19447ab3 100644
--- a/lib/services/local/git_server.go
+++ b/lib/services/local/git_server.go
@@ -23,6 +23,7 @@ import (
"github.com/gravitational/trace"
+ apidefaults "github.com/gravitational/teleport/api/defaults"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/defaults"
@@ -128,3 +129,44 @@ func (s *GitServerService) ListGitServers(ctx context.Context, pageSize int, pag
}
return items, next, nil
}
+
+func newGitServerParser() *gitServerParser {
+ return &gitServerParser{
+ baseParser: newBaseParser(backend.NewKey(gitServerPrefix)),
+ }
+}
+
+type gitServerParser struct {
+ baseParser
+}
+
+func (p *gitServerParser) parse(event backend.Event) (types.Resource, error) {
+ switch event.Type {
+ case types.OpDelete:
+ components := event.Item.Key.Components()
+ if len(components) < 2 {
+ return nil, trace.NotFound("failed parsing %s", event.Item.Key)
+ }
+
+ return &types.ResourceHeader{
+ Kind: types.KindGitServer,
+ Version: types.V2,
+ Metadata: types.Metadata{
+ Name: components[1],
+ Namespace: apidefaults.Namespace,
+ },
+ }, nil
+ case types.OpPut:
+ resource, err := services.UnmarshalServer(event.Item.Value,
+ types.KindGitServer,
+ services.WithExpires(event.Item.Expires),
+ services.WithRevision(event.Item.Revision),
+ )
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+ return resource, nil
+ default:
+ return nil, trace.BadParameter("event %v is not supported", event.Type)
+ }
+}
diff --git a/tool/tctl/common/resource_command.go b/tool/tctl/common/resource_command.go
index 66a916c6711b1..e8d798d8c7896 100644
--- a/tool/tctl/common/resource_command.go
+++ b/tool/tctl/common/resource_command.go
@@ -49,7 +49,6 @@ import (
dbobjectv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/dbobject/v1"
dbobjectimportrulev1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/dbobjectimportrule/v1"
devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1"
- gitserverv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/gitserver/v1"
loginrulepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/loginrule/v1"
machineidv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/machineid/v1"
pluginsv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/plugins/v1"
@@ -1980,7 +1979,7 @@ func (rc *ResourceCommand) Delete(ctx context.Context, client *authclient.Client
}
fmt.Printf("static host user %q has been deleted\n", rc.ref.Name)
case types.KindGitServer:
- if _, err := client.GitServerClient().DeleteGitServer(ctx, &gitserverv1.DeleteGitServerRequest{Name: rc.ref.Name}); err != nil {
+ if err := client.GitServerClient().DeleteGitServer(ctx, rc.ref.Name); err != nil {
return trace.Wrap(err)
}
fmt.Printf("git_server %q has been deleted\n", rc.ref.Name)
@@ -3232,29 +3231,27 @@ func (rc *ResourceCommand) getCollection(ctx context.Context, client *authclient
}
return &accessMonitoringRuleCollection{items: rules}, nil
case types.KindGitServer:
- var servers []types.Server
+ var page, servers []types.Server
// TODO(greedy52) use unified resource request once available.
if rc.ref.Name != "" {
- server, err := client.GitServerClient().GetGitServer(ctx, &gitserverv1.GetGitServerRequest{Name: rc.ref.Name})
+ server, err := client.GitServerClient().GetGitServer(ctx, rc.ref.Name)
if err != nil {
return nil, trace.Wrap(err)
}
return &serverCollection{servers: append(servers, server)}, nil
}
- req := &gitserverv1.ListGitServersRequest{}
+ var err error
+ var token string
for {
- resp, err := client.GitServerClient().ListGitServers(ctx, req)
+ page, token, err = client.GitServerClient().ListGitServers(ctx, 0, token)
if err != nil {
return nil, trace.Wrap(err)
}
- for _, server := range resp.Servers {
- servers = append(servers, server)
- }
- if resp.NextPageToken == "" {
+ servers = append(servers, page...)
+ if token == "" {
break
}
- req.PageToken = resp.NextPageToken
}
// TODO(greedy52) consider making dedicated git server collection.
return &serverCollection{servers: servers}, nil
@@ -3676,14 +3673,10 @@ func (rc *ResourceCommand) createGitServer(ctx context.Context, client *authclie
if err != nil {
return trace.Wrap(err)
}
- serverV2, ok := server.(*types.ServerV2)
- if !ok {
- return trace.CompareFailed("expecting types.ServerV2 but got %T", server)
- }
if rc.IsForced() {
- _, err = client.GitServerClient().UpsertGitServer(ctx, &gitserverv1.UpsertGitServerRequest{Server: serverV2})
+ _, err = client.GitServerClient().UpsertGitServer(ctx, server)
} else {
- _, err = client.GitServerClient().CreateGitServer(ctx, &gitserverv1.CreateGitServerRequest{Server: serverV2})
+ _, err = client.GitServerClient().CreateGitServer(ctx, server)
}
if err != nil {
return trace.Wrap(err)
@@ -3696,11 +3689,7 @@ func (rc *ResourceCommand) updateGitServer(ctx context.Context, client *authclie
if err != nil {
return trace.Wrap(err)
}
- serverV2, ok := server.(*types.ServerV2)
- if !ok {
- return trace.CompareFailed("expecting types.ServerV2 but got %T", server)
- }
- _, err = client.GitServerClient().UpdateGitServer(ctx, &gitserverv1.UpdateGitServerRequest{Server: serverV2})
+ _, err = client.GitServerClient().UpdateGitServer(ctx, server)
if err != nil {
return trace.Wrap(err)
}