mirror of
https://github.com/portainer/portainer.git
synced 2025-07-21 14:29:40 +02:00
fix(app): properly update the app state when losing connectivity to a remote environment while browsing it (#11942)
Some checks are pending
ci / build_images (map[arch:amd64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
ci / build_images (map[arch:arm platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:arm64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:ppc64le platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:s390x platform:linux version:]) (push) Waiting to run
ci / build_manifests (push) Blocked by required conditions
/ triage (push) Waiting to run
Lint / Run linters (push) Waiting to run
Test / test-client (push) Waiting to run
Test / test-server (map[arch:amd64 platform:linux]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
Test / test-server (map[arch:arm64 platform:linux]) (push) Waiting to run
Some checks are pending
ci / build_images (map[arch:amd64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
ci / build_images (map[arch:arm platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:arm64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:ppc64le platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:s390x platform:linux version:]) (push) Waiting to run
ci / build_manifests (push) Blocked by required conditions
/ triage (push) Waiting to run
Lint / Run linters (push) Waiting to run
Test / test-client (push) Waiting to run
Test / test-server (map[arch:amd64 platform:linux]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
Test / test-server (map[arch:arm64 platform:linux]) (push) Waiting to run
This commit is contained in:
parent
bfa27d9103
commit
9994ed157a
4 changed files with 57 additions and 31 deletions
|
@ -16,7 +16,7 @@ angular.module('portainer.docker', ['portainer.app', reactModule]).config([
|
||||||
parent: 'endpoint',
|
parent: 'endpoint',
|
||||||
url: '/docker',
|
url: '/docker',
|
||||||
abstract: true,
|
abstract: true,
|
||||||
onEnter: /* @ngInject */ function onEnter(endpoint, $async, $state, EndpointService, Notifications, StateManager, SystemService) {
|
onEnter: /* @ngInject */ function onEnter(endpoint, $async, $state, EndpointService, Notifications, StateManager, SystemService, EndpointProvider) {
|
||||||
return $async(async () => {
|
return $async(async () => {
|
||||||
const dockerTypes = [PortainerEndpointTypes.DockerEnvironment, PortainerEndpointTypes.AgentOnDockerEnvironment, PortainerEndpointTypes.EdgeAgentOnDockerEnvironment];
|
const dockerTypes = [PortainerEndpointTypes.DockerEnvironment, PortainerEndpointTypes.AgentOnDockerEnvironment, PortainerEndpointTypes.EdgeAgentOnDockerEnvironment];
|
||||||
|
|
||||||
|
@ -44,9 +44,11 @@ angular.module('portainer.docker', ['portainer.app', reactModule]).config([
|
||||||
if (endpoint.Type == PortainerEndpointTypes.EdgeAgentOnDockerEnvironment) {
|
if (endpoint.Type == PortainerEndpointTypes.EdgeAgentOnDockerEnvironment) {
|
||||||
params = { redirect: true, environmentId: endpoint.Id, environmentName: endpoint.Name, route: 'docker.dashboard' };
|
params = { redirect: true, environmentId: endpoint.Id, environmentName: endpoint.Name, route: 'docker.dashboard' };
|
||||||
} else {
|
} else {
|
||||||
|
EndpointProvider.clean();
|
||||||
Notifications.error('Failed loading environment', e);
|
Notifications.error('Failed loading environment', e);
|
||||||
}
|
}
|
||||||
$state.go('portainer.home', params, { reload: true, inherit: false });
|
$state.go('portainer.home', params, { reload: true, inherit: false });
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkEndpointStatus(endpoint) {
|
async function checkEndpointStatus(endpoint) {
|
||||||
|
|
|
@ -63,12 +63,13 @@ angular.module('portainer.kubernetes', ['portainer.app', registriesModule, custo
|
||||||
$state,
|
$state,
|
||||||
endpoint,
|
endpoint,
|
||||||
KubernetesHealthService,
|
KubernetesHealthService,
|
||||||
KubernetesNamespaceService,
|
|
||||||
Notifications,
|
Notifications,
|
||||||
StateManager,
|
StateManager,
|
||||||
$http,
|
$http,
|
||||||
Authentication,
|
Authentication,
|
||||||
UserService
|
UserService,
|
||||||
|
EndpointService,
|
||||||
|
EndpointProvider
|
||||||
) {
|
) {
|
||||||
return $async(async () => {
|
return $async(async () => {
|
||||||
// if the user wants to use front end cache for performance, set the angular caching settings
|
// if the user wants to use front end cache for performance, set the angular caching settings
|
||||||
|
@ -93,39 +94,57 @@ angular.module('portainer.kubernetes', ['portainer.app', registriesModule, custo
|
||||||
$state.go('portainer.home');
|
$state.go('portainer.home');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (endpoint.Type === PortainerEndpointTypes.EdgeAgentOnKubernetesEnvironment) {
|
const status = await checkEndpointStatus(
|
||||||
//edge
|
endpoint.Type === PortainerEndpointTypes.EdgeAgentOnKubernetesEnvironment
|
||||||
try {
|
? KubernetesHealthService.ping(endpoint.Id)
|
||||||
await KubernetesHealthService.ping(endpoint.Id);
|
: // use selfsubject access review to check if we can connect to the kubernetes environment
|
||||||
endpoint.Status = EnvironmentStatus.Up;
|
// because it gets a fast response, and is accessible to all users
|
||||||
} catch (e) {
|
getSelfSubjectAccessReview(endpoint.Id, 'default')
|
||||||
endpoint.Status = EnvironmentStatus.Down;
|
);
|
||||||
|
|
||||||
|
if (endpoint.Type !== PortainerEndpointTypes.EdgeAgentOnKubernetesEnvironment) {
|
||||||
|
await updateEndpointStatus(endpoint, status);
|
||||||
}
|
}
|
||||||
|
endpoint.Status = status;
|
||||||
|
|
||||||
|
if (endpoint.Status === EnvironmentStatus.Down) {
|
||||||
|
throw new Error(
|
||||||
|
endpoint.Type === PortainerEndpointTypes.EdgeAgentOnKubernetesEnvironment
|
||||||
|
? 'Unable to contact Edge agent, please ensure that the agent is properly running on the remote environment.'
|
||||||
|
: `The environment named ${endpoint.Name} is unreachable.`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await StateManager.updateEndpointState(endpoint);
|
await StateManager.updateEndpointState(endpoint);
|
||||||
|
|
||||||
if (endpoint.Type === PortainerEndpointTypes.EdgeAgentOnKubernetesEnvironment && endpoint.Status === EnvironmentStatus.Down) {
|
|
||||||
throw new Error('Unable to contact Edge agent, please ensure that the agent is properly running on the remote environment.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// use selfsubject access review to check if we can connect to the kubernetes environment
|
|
||||||
// because it's gets a fast response, and is accessible to all users
|
|
||||||
try {
|
|
||||||
await getSelfSubjectAccessReview(endpoint.Id, 'default');
|
|
||||||
} catch (e) {
|
|
||||||
throw new Error(`The environment named ${endpoint.Name} is unreachable.`);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
let params = {};
|
let params = {};
|
||||||
|
|
||||||
if (endpoint.Type == PortainerEndpointTypes.EdgeAgentOnKubernetesEnvironment) {
|
if (endpoint.Type == PortainerEndpointTypes.EdgeAgentOnKubernetesEnvironment) {
|
||||||
params = { redirect: true, environmentId: endpoint.Id, environmentName: endpoint.Name, route: 'kubernetes.dashboard' };
|
params = { redirect: true, environmentId: endpoint.Id, environmentName: endpoint.Name, route: 'kubernetes.dashboard' };
|
||||||
} else {
|
} else {
|
||||||
|
EndpointProvider.clean();
|
||||||
Notifications.error('Failed loading environment', e);
|
Notifications.error('Failed loading environment', e);
|
||||||
}
|
}
|
||||||
$state.go('portainer.home', params, { reload: true, inherit: false });
|
$state.go('portainer.home', params, { reload: true, inherit: false });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkEndpointStatus(promise) {
|
||||||
|
try {
|
||||||
|
await promise;
|
||||||
|
return EnvironmentStatus.Up;
|
||||||
|
} catch (e) {
|
||||||
|
return EnvironmentStatus.Down;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateEndpointStatus(endpoint, status) {
|
||||||
|
if (endpoint.Status === status) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await EndpointService.updateEndpoint(endpoint.Id, { Status: status });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,8 +4,6 @@ import { setupCache, buildMemoryStorage } from 'axios-cache-interceptor';
|
||||||
|
|
||||||
import { buildDockerProxyUrl } from '@/react/docker/proxy/queries/buildDockerProxyUrl';
|
import { buildDockerProxyUrl } from '@/react/docker/proxy/queries/buildDockerProxyUrl';
|
||||||
|
|
||||||
import PortainerError from '../error';
|
|
||||||
|
|
||||||
import { MAX_DOCKER_API_VERSION } from './dockerMaxApiVersion';
|
import { MAX_DOCKER_API_VERSION } from './dockerMaxApiVersion';
|
||||||
|
|
||||||
const envVersionAxios = Axios.create({
|
const envVersionAxios = Axios.create({
|
||||||
|
@ -56,9 +54,7 @@ export async function dockerMaxAPIVersionInterceptor(
|
||||||
}
|
}
|
||||||
return config;
|
return config;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new PortainerError(
|
// if the interceptor errors, return the original config
|
||||||
'An error occurred while trying to limit request to the maximum supported Docker API version',
|
return rawConfig;
|
||||||
err
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
import { useStore } from 'zustand';
|
||||||
import { useCurrentStateAndParams, useRouter } from '@uirouter/react';
|
import { useCurrentStateAndParams, useRouter } from '@uirouter/react';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
import { environmentStore } from '@/react/hooks/current-environment-store';
|
||||||
import { Environment } from '@/react/portainer/environments/types';
|
import { Environment } from '@/react/portainer/environments/types';
|
||||||
import { snapshotEndpoints } from '@/react/portainer/environments/environment.service';
|
import { snapshotEndpoints } from '@/react/portainer/environments/environment.service';
|
||||||
import { isEdgeEnvironment } from '@/react/portainer/environments/utils';
|
import { isEdgeEnvironment } from '@/react/portainer/environments/utils';
|
||||||
|
@ -18,6 +20,8 @@ import { LicenseNodePanel } from './LicenseNodePanel';
|
||||||
import { BackupFailedPanel } from './BackupFailedPanel';
|
import { BackupFailedPanel } from './BackupFailedPanel';
|
||||||
|
|
||||||
export function HomeView() {
|
export function HomeView() {
|
||||||
|
const { clear: clearStore } = useStore(environmentStore);
|
||||||
|
|
||||||
const { params } = useCurrentStateAndParams();
|
const { params } = useCurrentStateAndParams();
|
||||||
const [connectingToEdgeEndpoint, setConnectingToEdgeEndpoint] = useState(
|
const [connectingToEdgeEndpoint, setConnectingToEdgeEndpoint] = useState(
|
||||||
!!params.redirect
|
!!params.redirect
|
||||||
|
@ -40,14 +44,19 @@ export function HomeView() {
|
||||||
endpointId: params.environmentId,
|
endpointId: params.environmentId,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
router.stateService.go('portainer.home', {}, { inherit: false });
|
clearStore();
|
||||||
|
router.stateService.go(
|
||||||
|
'portainer.home',
|
||||||
|
{},
|
||||||
|
{ reload: true, inherit: false }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.redirect) {
|
if (params.redirect) {
|
||||||
redirect();
|
redirect();
|
||||||
}
|
}
|
||||||
}, [params, setConnectingToEdgeEndpoint, router]);
|
}, [params, setConnectingToEdgeEndpoint, router, clearStore]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue