diff --git a/src/rest-server/docs/swagger.yaml b/src/rest-server/docs/swagger.yaml index af1f913ddc5..4bcfd44b861 100644 --- a/src/rest-server/docs/swagger.yaml +++ b/src/rest-server/docs/swagger.yaml @@ -1710,6 +1710,12 @@ paths: summary: Get kubernetes pod list. description: Get kubernetes pod list. Need administrator permission. operationId: getK8sPods + parameters: + - name: namespace + in: query + description: filter pods with namespace + schema: + type: string security: - bearerAuth: [] responses: diff --git a/src/rest-server/src/models/kubernetes.js b/src/rest-server/src/models/kubernetes.js index 8bdecfca50b..1c0c5a0c1aa 100644 --- a/src/rest-server/src/models/kubernetes.js +++ b/src/rest-server/src/models/kubernetes.js @@ -61,7 +61,7 @@ const getNodes = async () => { }; const getPods = async (options = {}) => { - const {labelSelector, negativeLabelSelector} = options; + const {labelSelector, negativeLabelSelector, namespace} = options; const client = getClient(); const labelSelectorStr = encodeSelector(labelSelector, negativeLabelSelector); const requestOptions = {}; @@ -70,7 +70,11 @@ const getPods = async (options = {}) => { labelSelector: labelSelectorStr, }; } - const res = await client.get('/api/v1/pods', requestOptions); + let url = '/api/v1/pods'; + if (namespace) { + url = `/api/v1/namespaces/${namespace}/pods`; + } + const res = await client.get(url, requestOptions); return res.data; }; diff --git a/src/rest-server/src/routes/kubernetes.js b/src/rest-server/src/routes/kubernetes.js index ee66cfc7c17..e2bf001ee52 100644 --- a/src/rest-server/src/routes/kubernetes.js +++ b/src/rest-server/src/routes/kubernetes.js @@ -29,7 +29,7 @@ router.route('/pods') return next(createError('Forbidden', 'ForbiddenUserError', `Non-admin is not allow to do this operation.`)); } try { - const pods = await kubernetes.getPods(); + const pods = await kubernetes.getPods({namespace: req.query.namespace}); res.status(200).json(pods); } catch (err) { next(err); diff --git a/src/webportal/src/app/cluster-view/services/service-info.js b/src/webportal/src/app/cluster-view/services/service-info.js index 4524bfd3778..da3f1a1e794 100644 --- a/src/webportal/src/app/cluster-view/services/service-info.js +++ b/src/webportal/src/app/cluster-view/services/service-info.js @@ -15,50 +15,58 @@ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// This function will call kubernetes restful api to get node - podlist - label info, to support service view monitor page. +const userAuth = require('../../user/user-auth/user-auth.component'); +const loading = require('../../job/loading/loading.component'); +const webportalConfig = require('../../config/webportal.config.js'); +const { clearToken } = require('../../user/user-logout/user-logout.component'); -import { isNil } from 'lodash'; - -export const getServiceView = (kubeURL, namespace, callback) => { - $.ajax({ - type: 'GET', - url: kubeURL + '/api/v1/nodes', - dataType: 'json', - success: function(data) { - const items = data.items; - const nodeList = []; - for (const item of items) { - nodeList.push(item); - } - getNodePods(kubeURL, namespace, nodeList, callback); +const fetchWrapper = async url => { + const token = userAuth.checkToken(); + const res = await fetch(url, { + headers: { + Authorization: `Bearer ${token}`, }, }); + if (res.ok) { + const data = await res.json(); + return data.items; + } else { + loading.hideLoading(); + if (res.status === 401) { + clearToken(); + } else { + const data = await res.json(); + alert(data.message); + } + } }; -const getNodePods = (kubeURL, namespace, nodeList, callback) => { - $.ajax({ - type: 'GET', - url: kubeURL + '/api/v1/namespaces/' + namespace + '/pods/', - dataType: 'json', - success: function(pods) { - const podsItems = pods.items; - const nodeDic = []; - - for (const pod of podsItems) { - const nodeName = pod.spec.nodeName; - if (nodeDic[nodeName] == null) { - nodeDic[nodeName] = []; - } - nodeDic[nodeName].push(pod); - } - const resultDic = []; - for (const node of nodeList) { - if (isNil(nodeDic[node.metadata.name])) { - nodeDic[node.metadata.name] = []; - } - resultDic.push({ node: node, podList: nodeDic[node.metadata.name] }); - } - callback(resultDic); - }, - }); +export const getServiceView = async callback => { + const nodeUrl = new URL( + '/api/v1/kubernetes/nodes', + webportalConfig.restServerUri, + ); + const podUrl = new URL( + '/api/v1/kubernetes/pods', + webportalConfig.restServerUri, + ); + podUrl.searchParams.set('namespace', 'default'); + const [nodes, pods] = await Promise.all([ + fetchWrapper(nodeUrl), + fetchWrapper(podUrl), + ]); + const resultDict = {}; + for (const node of nodes) { + resultDict[node.metadata.name] = { + node: node, + podList: [], + }; + } + for (const pod of pods) { + const nodeName = pod.spec.nodeName; + if (resultDict[nodeName]) { + resultDict[nodeName].podList.push(pod); + } + } + callback(Object.values(resultDict)); }; diff --git a/src/webportal/src/app/cluster-view/services/services.component.js b/src/webportal/src/app/cluster-view/services/services.component.js index e60cd7681dd..5e5c37448ea 100644 --- a/src/webportal/src/app/cluster-view/services/services.component.js +++ b/src/webportal/src/app/cluster-view/services/services.component.js @@ -16,6 +16,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // module dependencies +import 'core-js/stable'; +import 'regenerator-runtime/runtime'; +import 'whatwg-fetch'; import { getServiceView } from './service-info'; const breadcrumbComponent = require('../../job/breadcrumb/breadcrumb.component.ejs'); @@ -40,31 +43,27 @@ const serviceViewHtml = serviceViewComponent({ const loadServices = () => { loading.showLoading(); - getServiceView( - webportalConfig.restServerUri + '/api/v1/kubernetes', - 'default', - data => { - loading.hideLoading(); - $('#service-table').html( - serviceTableComponent({ - data, - k8sUri: webportalConfig.k8sDashboardUri, - grafanaUri: webportalConfig.grafanaUri, - exporterPort: webportalConfig.exporterPort, - }), - ); - $('#service-datatable') - .dataTable({ - scrollY: $(window).height() - 265 + 'px', - lengthMenu: [[20, 50, 100, -1], [20, 50, 100, 'All']], - columnDefs: [ - { orderDataType: 'dom-text', targets: [1, 2] }, - { type: 'ip-address', targets: [0] }, - ], - }) - .api(); - }, - ); + getServiceView(data => { + loading.hideLoading(); + $('#service-table').html( + serviceTableComponent({ + data, + k8sUri: webportalConfig.k8sDashboardUri, + grafanaUri: webportalConfig.grafanaUri, + exporterPort: webportalConfig.exporterPort, + }), + ); + $('#service-datatable') + .dataTable({ + scrollY: $(window).height() - 265 + 'px', + lengthMenu: [[20, 50, 100, -1], [20, 50, 100, 'All']], + columnDefs: [ + { orderDataType: 'dom-text', targets: [1, 2] }, + { type: 'ip-address', targets: [0] }, + ], + }) + .api(); + }); }; window.loadServices = loadServices; @@ -76,5 +75,3 @@ $('#content-wrapper').html(serviceViewHtml); $(document).ready(() => { loadServices(); }); - -module.exports = { loadServices };