Skip to content

Commit

Permalink
Merge branch 'main' into row-action-bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
skoeva authored Dec 20, 2024
2 parents 8a31aeb + b762a52 commit f785705
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 5 deletions.
2 changes: 1 addition & 1 deletion charts/headlamp/templates/pvc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ spec:
{{- end}}
resources:
requests:
storage: {{ .Values.persistentVolumeClaim.size }}
storage: {{ required "A valid .Values.persistentVolumeClaim.size entry required!" .Values.persistentVolumeClaim.size }}
{{- with .Values.persistentVolumeClaim.volumeMode }}
volumeMode: {{ . }}
{{- end }}
Expand Down
2 changes: 1 addition & 1 deletion docs/platforms.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The "works" column refers to the overall Kubernetes-related functionality when r
| [Microsoft AKS](https://azure.microsoft.com/) | ✔️ | - Working fine in-cluster and with the desktop application. |
| [Minikube](https://minikube.sigs.k8s.io/) | ✔️ | - For exposing with an ingress, enable ingresses with `minikube addons enable ingress`: <br/> - There are docs about the [development](./development/index.md#minikube-in-cluster) with Minikube. |
| [Vultr Kubernetes Engine](https://www.vultr.com/kubernetes/) | ✔️ | - Simple to install / expose with the regular [in-cluster instructions](https://headlamp.dev/docs/latest/installation/in-cluster/). |

| [Red Hat OpenShift](https://www.redhat.com/en/technologies/cloud-computing/openshift) | ✔️ | - Simple to install / expose with the regular [in-cluster instructions](https://headlamp.dev/docs/latest/installation/in-cluster/). |
## Tested Browsers

We mostly test with 'modern browsers' defined as the latest version and two older versions. But we try to make Headlamp work with web standards, so it's quite likely other standards-conforming browsers will also work.
Expand Down
10 changes: 7 additions & 3 deletions frontend/src/components/common/ActionsNotifier.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,20 @@ function PureActionsNotifier({ dispatch, clusterActions }: PureActionsNotifierPr
}

const prevKey = snackbarRefs.current[clusterAction.id];
const uniqueKey = clusterAction.key || clusterAction.id;
const uniqueKey = `${clusterAction.key || clusterAction.id}-${Date.now()}`;

if (prevKey && prevKey !== uniqueKey) {
closeSnackbar(prevKey);
}

if (clusterAction.message) {
// Check for completed actions
// Check for success or error states
const refKey =
clusterAction.state === 'complete' ? `${clusterAction.id}-complete` : clusterAction.id;
clusterAction.state === 'complete'
? `${clusterAction.id}-complete`
: clusterAction.state === 'error'
? `${clusterAction.id}-error`
: clusterAction.id;

if (!snackbarRefs.current[refKey]) {
snackbarRefs.current[refKey] = uniqueKey;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import _ from 'lodash';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux';
import { useLocation } from 'react-router-dom';
import { KubeObject } from '../../../lib/k8s/KubeObject';
import { CallbackActionOptions, clusterAction } from '../../../redux/clusterActionSlice';
import {
Expand Down Expand Up @@ -43,6 +44,7 @@ export default function DeleteMultipleButton(props: DeleteMultipleButtonProps) {
const { items, options, afterConfirm, buttonStyle } = props;
const [openAlert, setOpenAlert] = React.useState(false);
const { t } = useTranslation(['translation']);
const location = useLocation();
const dispatchDeleteEvent = useEventCallback(HeadlampEventType.DELETE_RESOURCES);

const deleteFunc = React.useCallback(
Expand Down
50 changes: 50 additions & 0 deletions frontend/src/lib/k8s/api/v2/useKubeObjectList.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
kubeObjectListQuery,
ListResponse,
makeListRequests,
useKubeObjectList,
useWatchKubeObjectLists,
} from './useKubeObjectList';
import * as websocket from './webSocket';
Expand Down Expand Up @@ -81,6 +82,16 @@ const mockClass = class {
static apiVersion = 'v1';
static apiName = 'pods';

static apiEndpoint = {
apiInfo: [
{
group: '',
resource: 'pods',
version: 'v1',
},
],
};

constructor(public jsonData: any) {}
} as any;

Expand Down Expand Up @@ -221,3 +232,42 @@ describe('useWatchKubeObjectLists', () => {
).toBe(objectB);
});
});

describe('useKubeObjectList', () => {
it('should call useKubeObjectList with 1 namespace after reducing amount of namespaces', async () => {
const spy = vi.spyOn(websocket, 'useWebSockets');
const queryClient = new QueryClient();

queryClient.setQueryData(['kubeObject', 'list', 'v1', 'pods', 'default', 'a', {}], {
list: { items: [], metadata: { resourceVersion: '0' } },
cluster: 'default',
namespace: 'a',
});
queryClient.setQueryData(['kubeObject', 'list', 'v1', 'pods', 'default', 'b', {}], {
list: { items: [], metadata: { resourceVersion: '0' } },
cluster: 'default',
namespace: 'b',
});

const result = renderHook(
(props: {}) =>
useKubeObjectList({
kubeObjectClass: mockClass,
requests: [{ cluster: 'default', namespaces: ['a', 'b'] }],
...props,
}),
{
wrapper: ({ children }) => (
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
),
}
);

result.rerender({ requests: [{ cluster: 'default', namespaces: ['a'] }] });

expect(spy.mock.calls[0][0].connections.length).toBe(0); // initial render
expect(spy.mock.calls[1][0].connections.length).toBe(2); // new connections with 'a' and 'b' namespaces
expect(spy.mock.calls[2][0].connections.length).toBe(2); // rerender with new props
expect(spy.mock.calls[3][0].connections.length).toBe(1); // updated connections after we removed namespace 'b'
});
});
13 changes: 13 additions & 0 deletions frontend/src/lib/k8s/api/v2/useKubeObjectList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,19 @@ export function useKubeObjectList<K extends KubeObject>({
setListsToWatch([...listsToWatch, ...listsNotYetWatched]);
}

const listsToStopWatching = listsToWatch.filter(
watching =>
requests.find(request =>
watching.cluster === request?.cluster && request.namespaces && watching.namespace
? request.namespaces?.includes(watching.namespace)
: true
) === undefined
);

if (listsToStopWatching.length > 0) {
setListsToWatch(listsToWatch.filter(it => !listsToStopWatching.includes(it)));
}

useWatchKubeObjectLists({
lists: shouldWatch ? listsToWatch : [],
endpoint,
Expand Down

0 comments on commit f785705

Please sign in to comment.