@@ -29,7 +29,6 @@ import (
2929 "reflect"
3030 "slices"
3131 "sort"
32- "strings"
3332 "time"
3433
3534 "github.com/alecthomas/kingpin/v2"
@@ -151,7 +150,6 @@ func (rc *ResourceCommand) Initialize(app *kingpin.Application, _ *tctlcfg.Globa
151150 types .KindNetworkRestrictions : rc .createNetworkRestrictions ,
152151 types .KindApp : rc .createApp ,
153152 types .KindAppServer : rc .createAppServer ,
154- types .KindDatabase : rc .createDatabase ,
155153 types .KindKubernetesCluster : rc .createKubeCluster ,
156154 types .KindToken : rc .createToken ,
157155 types .KindInstaller : rc .createInstaller ,
@@ -1322,29 +1320,6 @@ func (rc *ResourceCommand) updateUserTask(ctx context.Context, client *authclien
13221320 return nil
13231321}
13241322
1325- func (rc * ResourceCommand ) createDatabase (ctx context.Context , client * authclient.Client , raw services.UnknownResource ) error {
1326- database , err := services .UnmarshalDatabase (raw .Raw , services .DisallowUnknown ())
1327- if err != nil {
1328- return trace .Wrap (err )
1329- }
1330- database .SetOrigin (types .OriginDynamic )
1331- if err := client .CreateDatabase (ctx , database ); err != nil {
1332- if trace .IsAlreadyExists (err ) {
1333- if ! rc .force {
1334- return trace .AlreadyExists ("database %q already exists" , database .GetName ())
1335- }
1336- if err := client .UpdateDatabase (ctx , database ); err != nil {
1337- return trace .Wrap (err )
1338- }
1339- fmt .Printf ("database %q has been updated\n " , database .GetName ())
1340- return nil
1341- }
1342- return trace .Wrap (err )
1343- }
1344- fmt .Printf ("database %q has been created\n " , database .GetName ())
1345- return nil
1346- }
1347-
13481323func (rc * ResourceCommand ) createToken (ctx context.Context , client * authclient.Client , raw services.UnknownResource ) error {
13491324 token , err := services .UnmarshalProvisionToken (raw .Raw , services .DisallowUnknown ())
13501325 if err != nil {
@@ -1931,8 +1906,8 @@ func (rc *ResourceCommand) Delete(ctx context.Context, client *authclient.Client
19311906 return trace .Wrap (err )
19321907 }
19331908 resDesc := "database server"
1934- servers = filterByNameOrDiscoveredName (servers , rc .ref .Name )
1935- name , err := getOneResourceNameToDelete (servers , rc .ref , resDesc )
1909+ servers = resources . FilterByNameOrDiscoveredName (servers , rc .ref .Name )
1910+ name , err := resources . GetOneResourceNameToDelete (servers , rc .ref , resDesc )
19361911 if err != nil {
19371912 return trace .Wrap (err )
19381913 }
@@ -1953,31 +1928,15 @@ func (rc *ResourceCommand) Delete(ctx context.Context, client *authclient.Client
19531928 return trace .Wrap (err )
19541929 }
19551930 fmt .Printf ("application %q has been deleted\n " , rc .ref .Name )
1956- case types .KindDatabase :
1957- // TODO(okraport) DELETE IN v21.0.0, replace with regular Collect
1958- databases , err := clientutils .CollectWithFallback (ctx , client .ListDatabases , client .GetDatabases )
1959- if err != nil {
1960- return trace .Wrap (err )
1961- }
1962- resDesc := "database"
1963- databases = filterByNameOrDiscoveredName (databases , rc .ref .Name )
1964- name , err := getOneResourceNameToDelete (databases , rc .ref , resDesc )
1965- if err != nil {
1966- return trace .Wrap (err )
1967- }
1968- if err := client .DeleteDatabase (ctx , name ); err != nil {
1969- return trace .Wrap (err )
1970- }
1971- fmt .Printf ("%s %q has been deleted\n " , resDesc , name )
19721931 case types .KindKubernetesCluster :
19731932 // TODO(okraport) DELETE IN v21.0.0, replace with regular Collect
19741933 clusters , err := clientutils .CollectWithFallback (ctx , client .ListKubernetesClusters , client .GetKubernetesClusters )
19751934 if err != nil {
19761935 return trace .Wrap (err )
19771936 }
19781937 resDesc := "Kubernetes cluster"
1979- clusters = filterByNameOrDiscoveredName (clusters , rc .ref .Name )
1980- name , err := getOneResourceNameToDelete (clusters , rc .ref , resDesc )
1938+ clusters = resources . FilterByNameOrDiscoveredName (clusters , rc .ref .Name )
1939+ name , err := resources . GetOneResourceNameToDelete (clusters , rc .ref , resDesc )
19811940 if err != nil {
19821941 return trace .Wrap (err )
19831942 }
@@ -2052,8 +2011,8 @@ func (rc *ResourceCommand) Delete(ctx context.Context, client *authclient.Client
20522011 return trace .Wrap (err )
20532012 }
20542013 resDesc := "Kubernetes server"
2055- servers = filterByNameOrDiscoveredName (servers , rc .ref .Name )
2056- name , err := getOneResourceNameToDelete (servers , rc .ref , resDesc )
2014+ servers = resources . FilterByNameOrDiscoveredName (servers , rc .ref .Name )
2015+ name , err := resources . GetOneResourceNameToDelete (servers , rc .ref , resDesc )
20572016 if err != nil {
20582017 return trace .Wrap (err )
20592018 }
@@ -2720,7 +2679,7 @@ func (rc *ResourceCommand) getCollection(ctx context.Context, client *authclient
27202679 return & databaseServerCollection {servers : servers }, nil
27212680 }
27222681
2723- servers = filterByNameOrDiscoveredName (servers , rc .ref .Name )
2682+ servers = resources . FilterByNameOrDiscoveredName (servers , rc .ref .Name )
27242683 if len (servers ) == 0 {
27252684 return nil , trace .NotFound ("database server %q not found" , rc .ref .Name )
27262685 }
@@ -2736,7 +2695,7 @@ func (rc *ResourceCommand) getCollection(ctx context.Context, client *authclient
27362695 altNameFn := func (r types.KubeServer ) string {
27372696 return r .GetHostname ()
27382697 }
2739- servers = filterByNameOrDiscoveredName (servers , rc .ref .Name , altNameFn )
2698+ servers = resources . FilterByNameOrDiscoveredName (servers , rc .ref .Name , altNameFn )
27402699 if len (servers ) == 0 {
27412700 return nil , trace .NotFound ("Kubernetes server %q not found" , rc .ref .Name )
27422701 }
@@ -2783,21 +2742,6 @@ func (rc *ResourceCommand) getCollection(ctx context.Context, client *authclient
27832742 return nil , trace .Wrap (err )
27842743 }
27852744 return & appCollection {apps : []types.Application {app }}, nil
2786- case types .KindDatabase :
2787- // TODO(okraport): DELETE IN v21.0.0, replace with regular Collect
2788- databases , err := clientutils .CollectWithFallback (ctx , client .ListDatabases , client .GetDatabases )
2789- if err != nil {
2790- return nil , trace .Wrap (err )
2791- }
2792-
2793- if rc .ref .Name == "" {
2794- return & databaseCollection {databases : databases }, nil
2795- }
2796- databases = filterByNameOrDiscoveredName (databases , rc .ref .Name )
2797- if len (databases ) == 0 {
2798- return nil , trace .NotFound ("database %q not found" , rc .ref .Name )
2799- }
2800- return & databaseCollection {databases : databases }, nil
28012745 case types .KindKubernetesCluster :
28022746 // TODO(okraport) DELETE IN v21.0.0, replace with regular Collect
28032747 clusters , err := clientutils .CollectWithFallback (ctx , client .ListKubernetesClusters , client .GetKubernetesClusters )
@@ -2807,7 +2751,7 @@ func (rc *ResourceCommand) getCollection(ctx context.Context, client *authclient
28072751 if rc .ref .Name == "" {
28082752 return & kubeClusterCollection {clusters : clusters }, nil
28092753 }
2810- clusters = filterByNameOrDiscoveredName (clusters , rc .ref .Name )
2754+ clusters = resources . FilterByNameOrDiscoveredName (clusters , rc .ref .Name )
28112755 if len (clusters ) == 0 {
28122756 return nil , trace .NotFound ("Kubernetes cluster %q not found" , rc .ref .Name )
28132757 }
@@ -3802,105 +3746,6 @@ func findDeviceByIDOrTag(ctx context.Context, remote devicepb.DeviceTrustService
38023746 return nil , trace .BadParameter ("found multiple devices for asset tag %q, please retry using the device ID instead" , idOrTag )
38033747}
38043748
3805- // keepFn is a predicate function that returns true if a resource should be
3806- // retained by filterResources.
3807- type keepFn [T types.ResourceWithLabels ] func (T ) bool
3808-
3809- // filterResources takes a list of resources and returns a filtered list of
3810- // resources for which the `keep` predicate function returns true.
3811- func filterResources [T types.ResourceWithLabels ](resources []T , keep keepFn [T ]) []T {
3812- out := make ([]T , 0 , len (resources ))
3813- for _ , r := range resources {
3814- if keep (r ) {
3815- out = append (out , r )
3816- }
3817- }
3818- return out
3819- }
3820-
3821- // altNameFn is a func that returns an alternative name for a resource.
3822- type altNameFn [T types.ResourceWithLabels ] func (T ) string
3823-
3824- // filterByNameOrDiscoveredName filters resources by name or "discovered name".
3825- // It prefers exact name filtering first - if none of the resource names match
3826- // exactly (i.e. all of the resources are filtered out), then it retries and
3827- // filters the resources by "discovered name" of resource name instead, which
3828- // comes from an auto-discovery label.
3829- func filterByNameOrDiscoveredName [T types.ResourceWithLabels ](resources []T , prefixOrName string , extra ... altNameFn [T ]) []T {
3830- // prefer exact names
3831- out := filterByName (resources , prefixOrName , extra ... )
3832- if len (out ) == 0 {
3833- // fallback to looking for discovered name label matches.
3834- out = filterByDiscoveredName (resources , prefixOrName )
3835- }
3836- return out
3837- }
3838-
3839- // filterByName filters resources by exact name match.
3840- func filterByName [T types.ResourceWithLabels ](resources []T , name string , altNameFns ... altNameFn [T ]) []T {
3841- return filterResources (resources , func (r T ) bool {
3842- if r .GetName () == name {
3843- return true
3844- }
3845- for _ , altName := range altNameFns {
3846- if altName (r ) == name {
3847- return true
3848- }
3849- }
3850- return false
3851- })
3852- }
3853-
3854- // filterByDiscoveredName filters resources that have a "discovered name" label
3855- // that matches the given name.
3856- func filterByDiscoveredName [T types.ResourceWithLabels ](resources []T , name string ) []T {
3857- return filterResources (resources , func (r T ) bool {
3858- discoveredName , ok := r .GetLabel (types .DiscoveredNameLabel )
3859- return ok && discoveredName == name
3860- })
3861- }
3862-
3863- // getOneResourceNameToDelete checks a list of resources to ensure there is
3864- // exactly one resource name among them, and returns that name or an error.
3865- // Heartbeat resources can have the same name but different host ID, so this
3866- // still allows a user to delete multiple heartbeats of the same name, for
3867- // example `$ tctl rm db_server/someDB`.
3868- func getOneResourceNameToDelete [T types.ResourceWithLabels ](rs []T , ref services.Ref , resDesc string ) (string , error ) {
3869- seen := make (map [string ]struct {})
3870- for _ , r := range rs {
3871- seen [r .GetName ()] = struct {}{}
3872- }
3873- switch len (seen ) {
3874- case 1 : // need exactly one.
3875- return rs [0 ].GetName (), nil
3876- case 0 :
3877- return "" , trace .NotFound ("%v %q not found" , resDesc , ref .Name )
3878- default :
3879- names := make ([]string , 0 , len (rs ))
3880- for _ , r := range rs {
3881- names = append (names , r .GetName ())
3882- }
3883- msg := formatAmbiguousDeleteMessage (ref , resDesc , names )
3884- return "" , trace .BadParameter ("%s" , msg )
3885- }
3886- }
3887-
3888- // formatAmbiguousDeleteMessage returns a formatted message when a user is
3889- // attempting to delete multiple resources by an ambiguous prefix of the
3890- // resource names.
3891- func formatAmbiguousDeleteMessage (ref services.Ref , resDesc string , names []string ) string {
3892- slices .Sort (names )
3893- // choose an actual resource for the example in the error.
3894- exampleRef := ref
3895- exampleRef .Name = names [0 ]
3896- return fmt .Sprintf (`%s matches multiple auto-discovered %vs:
3897- %v
3898-
3899- Use the full resource name that was generated by the Teleport Discovery service, for example:
3900- $ tctl rm %s` ,
3901- ref .String (), resDesc , strings .Join (names , "\n " ), exampleRef .String ())
3902- }
3903-
39043749func (rc * ResourceCommand ) createAuditQuery (ctx context.Context , client * authclient.Client , raw services.UnknownResource ) error {
39053750 in , err := services .UnmarshalAuditQuery (raw .Raw , services .DisallowUnknown ())
39063751 if err != nil {
0 commit comments