Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,376 changes: 684 additions & 692 deletions gen/proto/go/teleport/lib/teleterm/v1/service.pb.go

Large diffs are not rendered by default.

14 changes: 1 addition & 13 deletions gen/proto/ts/teleport/lib/teleterm/v1/service_pb.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 7 additions & 5 deletions lib/teleterm/apiserver/handler/handler_kubes.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,18 @@ func (s *Handler) ListKubernetesResources(ctx context.Context, req *api.ListKube
return nil, trace.Wrap(err)
}

resp, err := s.DaemonService.ListKubernetesResources(ctx, clusterURI, req)
resources, err := s.DaemonService.ListKubernetesResources(ctx, clusterURI, req)
if err != nil {
return nil, trace.Wrap(err)
}

response := &api.ListKubernetesResourcesResponse{
NextKey: resp.NextKey,
}
response := &api.ListKubernetesResourcesResponse{}

for _, kubeResource := range resp.Resources {
for _, resource := range resources {
kubeResource, ok := resource.(*types.KubernetesResourceV1)
if !ok {
return nil, trace.BadParameter("expected resource type %T, got %T", types.KubernetesResourceV1{}, resource)
}
response.Resources = append(response.Resources, newApiKubeResource(kubeResource, req.GetKubernetesCluster(), clusterURI))
}

Expand Down
17 changes: 10 additions & 7 deletions lib/teleterm/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

apiclient "github.com/gravitational/teleport/api/client"
"github.com/gravitational/teleport/api/client/proto"
accesslistv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/accesslist/v1"
devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1"
Expand Down Expand Up @@ -799,21 +800,21 @@ func (s *Service) AssumeRole(ctx context.Context, req *api.AssumeRoleRequest) er

// ListKubernetesResourcesRequest defines a request to retrieve kube resources paginated.
// Only one type of kube resource can be retrieved per request (eg: namespace, pods, secrets, etc.)
func (s *Service) ListKubernetesResources(ctx context.Context, clusterURI uri.ResourceURI, req *api.ListKubernetesResourcesRequest) (*kubeproto.ListKubernetesResourcesResponse, error) {
cluster, tc, err := s.ResolveClusterURI(clusterURI)
func (s *Service) ListKubernetesResources(ctx context.Context, clusterURI uri.ResourceURI, req *api.ListKubernetesResourcesRequest) ([]types.ResourceWithLabels, error) {
_, tc, err := s.ResolveClusterURI(clusterURI)
if err != nil {
return nil, trace.Wrap(err)
}

var resources *kubeproto.ListKubernetesResourcesResponse
var resources []types.ResourceWithLabels

err = clusters.AddMetadataToRetryableError(ctx, func() error {
kubenetesServiceClient, err := tc.NewKubernetesServiceClient(ctx, cluster.Name)
kubeServiceClient, err := tc.NewKubernetesServiceClient(ctx, tc.SiteName)
if err != nil {
return trace.Wrap(err)
}

resources, err = kubenetesServiceClient.ListKubernetesResources(ctx, &kubeproto.ListKubernetesResourcesRequest{
req := &kubeproto.ListKubernetesResourcesRequest{
ResourceType: req.GetResourceType(),
Limit: req.GetLimit(),
StartKey: req.GetNextKey(),
Expand All @@ -822,8 +823,10 @@ func (s *Service) ListKubernetesResources(ctx context.Context, clusterURI uri.Re
UseSearchAsRoles: req.GetUseSearchAsRoles(),
KubernetesCluster: req.GetKubernetesCluster(),
KubernetesNamespace: req.GetKubernetesNamespace(),
TeleportCluster: cluster.Name,
})
TeleportCluster: tc.SiteName,
}

resources, err = apiclient.GetKubernetesResourcesWithFilters(ctx, kubeServiceClient, req)
Comment thread
gzdunek marked this conversation as resolved.
return trace.Wrap(err)
})

Expand Down
3 changes: 2 additions & 1 deletion proto/teleport/lib/teleterm/v1/service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,8 @@ message ListKubernetesResourcesRequest {

message ListKubernetesResourcesResponse {
repeated KubeResource resources = 1;
string next_key = 2;
reserved 2;
reserved "next_key";
}

// CredentialInfo holds fields related to a user's WebAuthn credential.
Expand Down
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Web UI still has this weird re-ordering because web UI still stores resource ids in a map which doesn't preserve order

Do you mean the JavaScript Map? It should preserve the insertion order. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no it's just a js object, now that you mention it... maybe it will be easy to just replace it with a js map (but not in this PR)

Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,19 @@ import { CheckableOptionComponent } from '../CheckableOption';

import { PendingListItem, PendingKubeResourceItem } from './RequestCheckout';

import type { KubeNamespaceRequest } from '../kube';

export function KubeNamespaceSelector({
kubeClusterItem,
fetchKubeNamespaces,
savedResourceItems,
bulkToggleKubeResources,
updateNamespacesForKubeCluster,
}: {
kubeClusterItem: PendingListItem;
fetchKubeNamespaces(p: KubeNamespaceRequest): Promise<string[]>;
fetchKubeNamespaces(
search: string,
kubeCluster: PendingListItem
): Promise<string[]>;
savedResourceItems: PendingListItem[];
bulkToggleKubeResources: (
updateNamespacesForKubeCluster: (
resources: PendingKubeResourceItem[],
resource: PendingListItem
) => void;
Expand All @@ -57,7 +58,9 @@ export function KubeNamespaceSelector({

const currKubeClustersNamespaceItems = savedResourceItems.filter(
resource =>
resource.kind === 'namespace' && resource.id === kubeClusterItem.id
resource.kind === 'namespace' &&
resource.id === kubeClusterItem.id &&
resource.clusterName === kubeClusterItem.clusterName
) as PendingKubeResourceItem[];

const [selectedOpts, setSelectedOpts] = useState<Option[]>(() =>
Expand All @@ -75,63 +78,42 @@ export function KubeNamespaceSelector({

switch (actionMeta.action) {
case 'clear':
bulkToggleKubeResources(
currKubeClustersNamespaceItems,
kubeClusterItem
);
updateNamespacesForKubeCluster([], kubeClusterItem);
return;
case 'remove-value':
bulkToggleKubeResources(
[
{
kind: 'namespace',
id: kubeClusterItem.id,
subResourceName: actionMeta.removedValue.value,
clusterName: kubeClusterItem.clusterName,
name: actionMeta.removedValue.value,
},
],
const selectedOptions = options || [];
updateNamespacesForKubeCluster(
selectedOptions.map(o => optionToKubeNamespace(o)),
kubeClusterItem
);
return;
}
}

const handleMenuClose = () => {
const selectedOptions = selectedOpts || [];
setIsMenuOpen(false);

const currNamespaces = currKubeClustersNamespaceItems.map(
n => n.subResourceName
);
const selectedNamespaceIds = selectedOpts.map(o => o.value);
const toKeep = selectedNamespaceIds.filter(id =>
currNamespaces.includes(id)
);

const toInsert = selectedNamespaceIds.filter(o => !toKeep.includes(o));
const toRemove = currNamespaces.filter(n => !toKeep.includes(n));

if (!toInsert.length && !toRemove.length) {
return;
}

bulkToggleKubeResources(
[...toRemove, ...toInsert].map(namespace => ({
kind: 'namespace',
id: kubeClusterItem.id,
subResourceName: namespace,
clusterName: kubeClusterItem.clusterName,
name: namespace,
})),
updateNamespacesForKubeCluster(
selectedOptions.map(o => optionToKubeNamespace(o)),
kubeClusterItem
);
};

function optionToKubeNamespace(
selectedOption: Option
): PendingKubeResourceItem {
const namespace = selectedOption.value;
return {
kind: 'namespace',
id: kubeClusterItem.id,
subResourceName: namespace,
clusterName: kubeClusterItem.clusterName,
name: namespace,
};
}

async function handleLoadOptions(input: string) {
const namespaces = await fetchKubeNamespaces({
kubeCluster: kubeClusterItem.id,
search: input,
});
const namespaces = await fetchKubeNamespaces(input, kubeClusterItem);

return namespaces.map(namespace => ({
kind: 'namespace',
Expand All @@ -141,10 +123,10 @@ export function KubeNamespaceSelector({
}

return (
<Box width="100%" mb={-3}>
<Box width="100%" mb={-3} mt={2}>
<StyledSelect
label={`Namespaces`}
Comment thread
gzdunek marked this conversation as resolved.
inputId={kubeClusterItem.id}
inputId={`${kubeClusterItem.id}-${kubeClusterItem.clusterName}`}
width="100%"
placeholder="Start typing a namespace and press enter"
isMulti
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ const baseProps: RequestCheckoutWithSliderProps = {
'namespace3',
'namespace4',
],
bulkToggleKubeResources: () => null,
updateNamespacesForKubeCluster: () => null,
createAttempt: { status: '' },
fetchResourceRequestRolesAttempt: { status: '' },
isResourceRequest: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,5 +175,5 @@ const props: RequestCheckoutWithSliderProps = {
startTime: null,
onStartTimeChange: () => null,
fetchKubeNamespaces: () => null,
bulkToggleKubeResources: () => null,
updateNamespacesForKubeCluster: () => null,
};
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ import { AccessDurationRequest } from '../../AccessDuration';
import {
checkSupportForKubeResources,
isKubeClusterWithNamespaces,
type KubeNamespaceRequest,
} from '../kube';

import { ReviewerOption } from './types';
Expand Down Expand Up @@ -170,7 +169,7 @@ export function RequestCheckout<T extends PendingListItem>({
startTime,
onStartTimeChange,
fetchKubeNamespaces,
bulkToggleKubeResources,
updateNamespacesForKubeCluster,
}: RequestCheckoutProps<T>) {
const [reason, setReason] = useState('');

Expand Down Expand Up @@ -241,7 +240,7 @@ export function RequestCheckout<T extends PendingListItem>({
function customRow(item: T) {
if (item.kind === 'kube_cluster') {
return (
<td colSpan={3}>
<td colSpan={showClusterNameColumn ? 4 : 3}>
<Flex>
<Flex flexWrap="wrap">
<Flex
Expand All @@ -251,6 +250,7 @@ export function RequestCheckout<T extends PendingListItem>({
alignItems="center"
>
<Flex gap={5}>
{showClusterNameColumn && <Box>{item.clusterName}</Box>}
<Box>{getPrettyResourceKind(item.kind)}</Box>
<Box>{item.name}</Box>
</Flex>
Expand All @@ -265,7 +265,7 @@ export function RequestCheckout<T extends PendingListItem>({
kubeClusterItem={item}
savedResourceItems={pendingAccessRequests}
fetchKubeNamespaces={fetchKubeNamespaces}
bulkToggleKubeResources={bulkToggleKubeResources}
updateNamespacesForKubeCluster={updateNamespacesForKubeCluster}
/>
</Flex>
</Flex>
Expand Down Expand Up @@ -934,8 +934,8 @@ export type RequestCheckoutProps<T extends PendingListItem = PendingListItem> =
Header?: () => JSX.Element;
startTime: Date;
onStartTimeChange(t?: Date): void;
fetchKubeNamespaces(p: KubeNamespaceRequest): Promise<string[]>;
bulkToggleKubeResources(
fetchKubeNamespaces(search: string, kubeCluster: T): Promise<string[]>;
updateNamespacesForKubeCluster(
kubeResources: PendingKubeResourceItem[],
kubeCluster: T
): void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,4 @@ export * from './RequestCheckout';
export * from './ResourceList';
export type { ResourceMap, RequestableResourceKind } from './resource';
export { getEmptyResourceState } from './resource';
export type { KubeNamespaceRequest } from './kube';
export { isKubeClusterWithNamespaces } from './kube';
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ import { Attempt } from 'shared/hooks/useAttemptNext';

import { PendingListItem } from './RequestCheckout';

export type KubeNamespaceRequest = {
kubeCluster: string;
search: string;
};

/**
* Returns true if the item is a kube cluster or is a namespace
* of the item.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export function AccessRequestCheckout() {
startTime,
onStartTimeChange,
fetchKubeNamespaces,
bulkToggleKubeResources,
updateNamespacesForKubeCluster,
} = useAccessRequestCheckout();

const isRoleRequest = pendingAccessRequests[0]?.kind === 'role';
Expand Down Expand Up @@ -284,7 +284,7 @@ export function AccessRequestCheckout() {
startTime={startTime}
onStartTimeChange={onStartTimeChange}
fetchKubeNamespaces={fetchKubeNamespaces}
bulkToggleKubeResources={bulkToggleKubeResources}
updateNamespacesForKubeCluster={updateNamespacesForKubeCluster}
/>
)}
</Transition>
Expand Down
Loading