diff --git a/frontend/src/hosts/actions/kubernetes.ts b/frontend/src/hosts/actions/kubernetes.ts index be7357d8..183b81f9 100644 --- a/frontend/src/hosts/actions/kubernetes.ts +++ b/frontend/src/hosts/actions/kubernetes.ts @@ -25,6 +25,7 @@ import { getLocalK8sRoleBindings, getLocalK8sPersistentVolumes, getLocalK8sPersistentVolumeClaims, + getLocalK8sDetail, } from 'src/shared/apis/saltStack' // Types @@ -52,6 +53,7 @@ export enum ActionTypes { RoleBindings = 'GET_ROLEBINDINGS', PersistentVolumes = 'GET_PERSISTENTVOLUMES', PersistentVolumeClaims = 'GET_PERSISTENTVOLUMECLAIMS', + K8sDetail = 'GET_K8S_DETAIL', } interface NamespacesAction { @@ -138,6 +140,10 @@ interface PersistentVolumeClaimsAction { type: ActionTypes.PersistentVolumeClaims } +interface K8sDetailAction { + type: ActionTypes.K8sDetail +} + export type Action = | NamespacesAction | NodesAction @@ -160,6 +166,7 @@ export type Action = | RoleBindingsAction | PersistentVolumesAction | PersistentVolumeClaimsAction + | K8sDetailAction export const loadNamespaces = (): NamespacesAction => ({ type: ActionTypes.Namespaces, @@ -245,6 +252,10 @@ export const loadPersistentVolumeClaims = (): PersistentVolumeClaimsAction => ({ type: ActionTypes.PersistentVolumeClaims, }) +export const loadK8sDetail = (): K8sDetailAction => ({ + type: ActionTypes.K8sDetail, +}) + export const getLocalK8sNamespacesAsync = ( pUrl: string, pToken: string, @@ -671,3 +682,20 @@ export const getLocalK8sPersistentVolumeClaimsAsync = ( dispatch(errorThrown(error)) } } + +export const getLocalK8sDetailAsync = ( + pUrl: string, + pToken: string, + pMinionId: string, + pParam?: SaltStack +) => async (dispatch: Dispatch) => { + try { + const k8sDetail = await getLocalK8sDetail(pUrl, pToken, pMinionId, pParam) + + dispatch(loadK8sDetail()) + return k8sDetail + } catch (error) { + console.error(error) + dispatch(errorThrown(error)) + } +} diff --git a/frontend/src/hosts/components/KubernetesContents.tsx b/frontend/src/hosts/components/KubernetesContents.tsx index b55460a0..e183bd96 100644 --- a/frontend/src/hosts/components/KubernetesContents.tsx +++ b/frontend/src/hosts/components/KubernetesContents.tsx @@ -33,7 +33,7 @@ import {Source, TimeRange, Cell, Template, RemoteDataState} from 'src/types' interface Props { handleOnSetActiveEditorTab: (tab: string) => void handleOnClickPodName: () => void - handleOnClickVisualizePod: (target: SVGSVGElement) => void + handleOnClickVisualizePod: (data: any) => void handleDBClick: (data: any) => void handleResize: (proportions: number[]) => void handleOpenTooltip: (target: any) => void @@ -231,28 +231,7 @@ class KubernetesContents extends PureComponent { -
- - - Basic - - - Raw Data - - -
+
Raw Data
{activeTab === 'Basic' ? ( ) : ( diff --git a/frontend/src/hosts/components/KubernetesHexagon.tsx b/frontend/src/hosts/components/KubernetesHexagon.tsx index afb2e6b2..7cd376ff 100644 --- a/frontend/src/hosts/components/KubernetesHexagon.tsx +++ b/frontend/src/hosts/components/KubernetesHexagon.tsx @@ -20,7 +20,7 @@ import {RemoteDataState} from 'src/types' interface Props { handleOnClickPodName: () => void - handleOnClickVisualizePod: (target: SVGSVGElement) => void + handleOnClickVisualizePod: (data: any) => void handleDBClick: (data: any) => void handleResize: (proportions: number[]) => void handleOpenTooltip: (target: any) => void @@ -209,7 +209,7 @@ class KubernetesHexagon extends PureComponent { .on('mouseleave', function () { onMouseLeave(this) }) - .on('click', function () { + .on('click', function (data) { onMouseClick(this, data) }) .on('mousedown', function () { @@ -347,56 +347,70 @@ class KubernetesHexagon extends PureComponent { _.forEach(kubernetesObject, m => { if (m['type'] === 'Node') { - const cpuUsage = - (parseFloat(m['cpu']) / - parseFloat( - node - .select(`circle[data-label=${m['name']}]`) - .attr('data-limit-cpu') - )) * - 100 - const memoryUsage = - (parseFloat(m['memory']) / - parseFloat( - node - .select(`circle[data-label=${m['name']}]`) - .attr('data-limit-memory') - )) * - 100 - const pick = cpuUsage > memoryUsage ? cpuUsage : memoryUsage - node - .select(`circle[data-label=${m['name']}]`) - .attr('data-cpu', `${cpuUsage}`) - node - .select(`circle[data-label=${m['name']}]`) - .attr('data-memory', `${memoryUsage}`) - .attr('fill', kubernetesStatusColor(pick / 100)) + if ( + _.find( + node.select(`circle[data-type=${'Node'}]`).data(), + nodeData => nodeData.data.label === m['name'] + ) + ) { + const cpuUsage = + (parseFloat(m['cpu']) / + parseFloat( + node + .select(`circle[data-label=${m['name']}]`) + .attr('data-limit-cpu') + )) * + 100 + const memoryUsage = + (parseFloat(m['memory']) / + parseFloat( + node + .select(`circle[data-label=${m['name']}]`) + .attr('data-limit-memory') + )) * + 100 + const pick = cpuUsage > memoryUsage ? cpuUsage : memoryUsage + node + .select(`circle[data-label=${m['name']}]`) + .attr('data-cpu', `${cpuUsage}`) + node + .select(`circle[data-label=${m['name']}]`) + .attr('data-memory', `${memoryUsage}`) + .attr('fill', kubernetesStatusColor(pick / 100)) + } } else { - const cpuUsage = - (parseFloat(m['cpu']) / - parseFloat( - node - .select(`path[data-label=${m['name']}]`) - .attr('data-limit-cpu') - )) * - 100 - const memoryUsage = - (parseFloat(m['memory']) / - parseFloat( - node - .select(`path[data-label=${m['name']}]`) - .attr('data-limit-memory') - )) * - 100 - - const pick = cpuUsage > memoryUsage ? cpuUsage : memoryUsage - node - .select(`path[data-label=${m['name']}]`) - .attr('data-cpu', `${cpuUsage}`) - node - .select(`path[data-label=${m['name']}]`) - .attr('data-memory', `${memoryUsage}`) - .attr('fill', kubernetesStatusColor(pick / 100)) + if ( + _.find( + node.select(`path[data-type=${'Pod'}]`).data(), + podData => podData.data.label === m['name'] + ) + ) { + const cpuUsage = + (parseFloat(m['cpu']) / + parseFloat( + node + .select(`path[data-label=${m['name']}]`) + .attr('data-limit-cpu') + )) * + 100 + const memoryUsage = + (parseFloat(m['memory']) / + parseFloat( + node + .select(`path[data-label=${m['name']}]`) + .attr('data-limit-memory') + )) * + 100 + + const pick = cpuUsage > memoryUsage ? cpuUsage : memoryUsage + node + .select(`path[data-label=${m['name']}]`) + .attr('data-cpu', `${cpuUsage}`) + node + .select(`path[data-label=${m['name']}]`) + .attr('data-memory', `${memoryUsage}`) + .attr('fill', kubernetesStatusColor(pick / 100)) + } } }) @@ -410,13 +424,13 @@ class KubernetesHexagon extends PureComponent { return this.ref.current.append(svg.attr('viewBox', `${autoBox()}`).node()) } - private runOnSingleClick = (target: SVGSVGElement) => { - this.props.handleOnClickVisualizePod(target) + private runOnSingleClick = (data: any) => { + this.props.handleOnClickVisualizePod(data) this.clickedOnce = false this.clickedTarget = null } - private runOnDBClick = (target: SVGSVGElement, data) => { + private runOnDBClick = (target: SVGSVGElement, data: any) => { this.clickedOnce = false this.clickedTarget = null clearTimeout(this.timeout) @@ -431,7 +445,7 @@ class KubernetesHexagon extends PureComponent { (this.clickedTarget !== target && this.clickedOnce) ) { this.timeout = setTimeout(() => { - this.runOnSingleClick(target) + this.runOnSingleClick(data) }, this.dbClickJudgementTimer) this.clickedTarget = target @@ -441,7 +455,7 @@ class KubernetesHexagon extends PureComponent { private onMouseDBClick = (target: SVGSVGElement, data: any) => { this.props.handleDBClick(data) - this.props.handleOnClickVisualizePod(target) + this.props.handleOnClickVisualizePod(data) } private onMouseOver = (target: SVGSVGElement) => { diff --git a/frontend/src/hosts/components/host.scss b/frontend/src/hosts/components/host.scss index 897c3d5f..9e0b12a0 100644 --- a/frontend/src/hosts/components/host.scss +++ b/frontend/src/hosts/components/host.scss @@ -214,6 +214,14 @@ } } +.kubernetes-detail-title { + height: 40px; + font-size: 15px; + font-weight: 600; + color: #bec2cc; + padding: 10px 5px 0 5px; +} + .devider--bar { background-color: $g2-kevlar; color: white; diff --git a/frontend/src/hosts/containers/Infrastructure.tsx b/frontend/src/hosts/containers/Infrastructure.tsx index 733ab38e..76a958d0 100644 --- a/frontend/src/hosts/containers/Infrastructure.tsx +++ b/frontend/src/hosts/containers/Infrastructure.tsx @@ -127,7 +127,7 @@ class Infrastructure extends PureComponent { const isUsingKubernetes = !_.isEmpty( _.find(addons, addon => { const {name, url} = addon - return name === 'kubernetes' && url === 'on' + return name === 'k8s' && url === 'on' }) ) diff --git a/frontend/src/hosts/containers/KubernetesPage.tsx b/frontend/src/hosts/containers/KubernetesPage.tsx index 02c14b68..cea196e9 100644 --- a/frontend/src/hosts/containers/KubernetesPage.tsx +++ b/frontend/src/hosts/containers/KubernetesPage.tsx @@ -1,7 +1,7 @@ // Library import React, {PureComponent, ChangeEvent} from 'react' import {connect} from 'react-redux' -import _ from 'lodash' +import _, {join} from 'lodash' import * as d3 from 'd3' import yaml from 'js-yaml' @@ -35,6 +35,7 @@ import { getLocalK8sRoleBindingsAsync, getLocalK8sPersistentVolumesAsync, getLocalK8sPersistentVolumeClaimsAsync, + getLocalK8sDetailAsync, } from 'src/hosts/actions/kubernetes' import {notify as notifyAction} from 'src/shared/actions/notifications' @@ -149,7 +150,7 @@ class KubernetesPage extends PureComponent { this.state = { ...this.defaultState, - activeEditorTab: 'Basic', + activeEditorTab: 'Detail', script: '', selectedNamespace: 'All namespaces', selectedNode: 'All nodes', @@ -243,7 +244,7 @@ class KubernetesPage extends PureComponent { ? `${filterLabelKey}=${filterLabelValue}` : '', namespace: `${filterNamespace}`, - limit: 100, + limit: filterLimit !== '' ? parseInt(filterLimit) : 100, }, } @@ -265,7 +266,12 @@ class KubernetesPage extends PureComponent { } public getDeployments = async () => { - const {selectMinion, filterNamespace} = this.state + const { + selectMinion, + filterNamespace, + filterLabelKey, + filterLabelValue, + } = this.state const addon = this.props.addons.find(addon => { return addon.name === AddonType.salt }) @@ -273,7 +279,14 @@ class KubernetesPage extends PureComponent { const saltMasterUrl = addon.url const saltMasterToken = addon.token const pParam: SaltStack = { - kwarg: {namespace: `${filterNamespace}`, detail: true}, + kwarg: { + namespace: `${filterNamespace}`, + labelselector: + !_.isEmpty(filterLabelKey) && !_.isEmpty(filterLabelValue) + ? `${filterLabelKey}=${filterLabelValue}` + : '', + detail: true, + }, } const deployments = await this.props.handleGetDeployments( @@ -294,7 +307,12 @@ class KubernetesPage extends PureComponent { } public getReplicaSets = async () => { - const {selectMinion, filterNamespace} = this.state + const { + selectMinion, + filterNamespace, + filterLabelKey, + filterLabelValue, + } = this.state const addon = this.props.addons.find(addon => { return addon.name === AddonType.salt }) @@ -302,7 +320,14 @@ class KubernetesPage extends PureComponent { const saltMasterUrl = addon.url const saltMasterToken = addon.token const pParam: SaltStack = { - kwarg: {namespace: `${filterNamespace}`, detail: true}, + kwarg: { + namespace: `${filterNamespace}`, + labelselector: + !_.isEmpty(filterLabelKey) && !_.isEmpty(filterLabelValue) + ? `${filterLabelKey}=${filterLabelValue}` + : '', + detail: true, + }, } const replicaSets = await this.props.handleGetReplicaSets( @@ -323,7 +348,12 @@ class KubernetesPage extends PureComponent { } public getReplicationControllers = async () => { - const {selectMinion, filterNamespace} = this.state + const { + selectMinion, + filterNamespace, + filterLabelKey, + filterLabelValue, + } = this.state const addon = this.props.addons.find(addon => { return addon.name === AddonType.salt }) @@ -331,7 +361,14 @@ class KubernetesPage extends PureComponent { const saltMasterUrl = addon.url const saltMasterToken = addon.token const pParam: SaltStack = { - kwarg: {namespace: `${filterNamespace}`, detail: true}, + kwarg: { + namespace: `${filterNamespace}`, + labelselector: + !_.isEmpty(filterLabelKey) && !_.isEmpty(filterLabelValue) + ? `${filterLabelKey}=${filterLabelValue}` + : '', + detail: true, + }, } const replicationControllers = await this.props.handleGetReplicationControllers( @@ -352,7 +389,12 @@ class KubernetesPage extends PureComponent { } public getDaemonSets = async () => { - const {selectMinion, filterNamespace} = this.state + const { + selectMinion, + filterNamespace, + filterLabelKey, + filterLabelValue, + } = this.state const addon = this.props.addons.find(addon => { return addon.name === AddonType.salt }) @@ -360,7 +402,14 @@ class KubernetesPage extends PureComponent { const saltMasterUrl = addon.url const saltMasterToken = addon.token const pParam: SaltStack = { - kwarg: {namespace: `${filterNamespace}`, detail: true}, + kwarg: { + namespace: `${filterNamespace}`, + labelselector: + !_.isEmpty(filterLabelKey) && !_.isEmpty(filterLabelValue) + ? `${filterLabelKey}=${filterLabelValue}` + : '', + detail: true, + }, } const daemonSets = await this.props.handleGetDaemonSets( @@ -381,7 +430,12 @@ class KubernetesPage extends PureComponent { } public getStatefulSets = async () => { - const {selectMinion, filterNamespace} = this.state + const { + selectMinion, + filterNamespace, + filterLabelKey, + filterLabelValue, + } = this.state const addon = this.props.addons.find(addon => { return addon.name === AddonType.salt }) @@ -389,7 +443,14 @@ class KubernetesPage extends PureComponent { const saltMasterUrl = addon.url const saltMasterToken = addon.token const pParam: SaltStack = { - kwarg: {namespace: `${filterNamespace}`, detail: true}, + kwarg: { + namespace: `${filterNamespace}`, + labelselector: + !_.isEmpty(filterLabelKey) && !_.isEmpty(filterLabelValue) + ? `${filterLabelKey}=${filterLabelValue}` + : '', + detail: true, + }, } const statefulSets = await this.props.handleGetStatefulSets( @@ -410,7 +471,12 @@ class KubernetesPage extends PureComponent { } public getCronJobs = async () => { - const {selectMinion, filterNamespace} = this.state + const { + selectMinion, + filterNamespace, + filterLabelKey, + filterLabelValue, + } = this.state const addon = this.props.addons.find(addon => { return addon.name === AddonType.salt }) @@ -418,7 +484,14 @@ class KubernetesPage extends PureComponent { const saltMasterUrl = addon.url const saltMasterToken = addon.token const pParam: SaltStack = { - kwarg: {namespace: `${filterNamespace}`, detail: true}, + kwarg: { + namespace: `${filterNamespace}`, + labelselector: + !_.isEmpty(filterLabelKey) && !_.isEmpty(filterLabelValue) + ? `${filterLabelKey}=${filterLabelValue}` + : '', + detail: true, + }, } const cronJobs = await this.props.handleGetCronJobs( @@ -439,7 +512,12 @@ class KubernetesPage extends PureComponent { } public getJobs = async () => { - const {selectMinion, filterNamespace} = this.state + const { + selectMinion, + filterNamespace, + filterLabelKey, + filterLabelValue, + } = this.state const addon = this.props.addons.find(addon => { return addon.name === AddonType.salt }) @@ -447,7 +525,14 @@ class KubernetesPage extends PureComponent { const saltMasterUrl = addon.url const saltMasterToken = addon.token const pParam: SaltStack = { - kwarg: {namespace: `${filterNamespace}`, detail: true}, + kwarg: { + namespace: `${filterNamespace}`, + labelselector: + !_.isEmpty(filterLabelKey) && !_.isEmpty(filterLabelValue) + ? `${filterLabelKey}=${filterLabelValue}` + : '', + detail: true, + }, } const jobs = await this.props.handleGetJobs( @@ -468,7 +553,12 @@ class KubernetesPage extends PureComponent { } public getServices = async flag => { - const {selectMinion, filterNamespace} = this.state + const { + selectMinion, + filterNamespace, + filterLabelKey, + filterLabelValue, + } = this.state const addon = this.props.addons.find(addon => { return addon.name === AddonType.salt }) @@ -476,7 +566,14 @@ class KubernetesPage extends PureComponent { const saltMasterUrl = addon.url const saltMasterToken = addon.token const pParam: SaltStack = { - kwarg: {namespace: `${filterNamespace}`, detail: true}, + kwarg: { + namespace: `${filterNamespace}`, + labelselector: + !_.isEmpty(filterLabelKey) && !_.isEmpty(filterLabelValue) + ? `${filterLabelKey}=${filterLabelValue}` + : '', + detail: true, + }, } if (flag) { @@ -500,7 +597,12 @@ class KubernetesPage extends PureComponent { } public getIngresses = async flag => { - const {selectMinion, filterNamespace} = this.state + const { + selectMinion, + filterNamespace, + filterLabelKey, + filterLabelValue, + } = this.state const addon = this.props.addons.find(addon => { return addon.name === AddonType.salt }) @@ -508,7 +610,14 @@ class KubernetesPage extends PureComponent { const saltMasterUrl = addon.url const saltMasterToken = addon.token const pParam: SaltStack = { - kwarg: {namespace: `${filterNamespace}`, detail: true}, + kwarg: { + namespace: `${filterNamespace}`, + labelselector: + !_.isEmpty(filterLabelKey) && !_.isEmpty(filterLabelValue) + ? `${filterLabelKey}=${filterLabelValue}` + : '', + detail: true, + }, } if (flag) { @@ -533,7 +642,12 @@ class KubernetesPage extends PureComponent { } public getConfigmaps = async () => { - const {selectMinion, filterNamespace} = this.state + const { + selectMinion, + filterNamespace, + filterLabelKey, + filterLabelValue, + } = this.state const addon = this.props.addons.find(addon => { return addon.name === AddonType.salt }) @@ -541,7 +655,14 @@ class KubernetesPage extends PureComponent { const saltMasterUrl = addon.url const saltMasterToken = addon.token const pParam: SaltStack = { - kwarg: {namespace: `${filterNamespace}`, detail: true}, + kwarg: { + namespace: `${filterNamespace}`, + labelselector: + !_.isEmpty(filterLabelKey) && !_.isEmpty(filterLabelValue) + ? `${filterLabelKey}=${filterLabelValue}` + : '', + detail: true, + }, } const configmaps = await this.props.handleGetConfigmaps( @@ -562,7 +683,12 @@ class KubernetesPage extends PureComponent { } public getSecrets = async () => { - const {selectMinion, filterNamespace} = this.state + const { + selectMinion, + filterNamespace, + filterLabelKey, + filterLabelValue, + } = this.state const addon = this.props.addons.find(addon => { return addon.name === AddonType.salt }) @@ -570,7 +696,14 @@ class KubernetesPage extends PureComponent { const saltMasterUrl = addon.url const saltMasterToken = addon.token const pParam: SaltStack = { - kwarg: {namespace: `${filterNamespace}`, detail: true}, + kwarg: { + namespace: `${filterNamespace}`, + labelselector: + !_.isEmpty(filterLabelKey) && !_.isEmpty(filterLabelValue) + ? `${filterLabelKey}=${filterLabelValue}` + : '', + detail: true, + }, } const secrets = await this.props.handleGetSecrets( @@ -591,7 +724,12 @@ class KubernetesPage extends PureComponent { } public getServiceAccounts = async () => { - const {selectMinion, filterNamespace} = this.state + const { + selectMinion, + filterNamespace, + filterLabelKey, + filterLabelValue, + } = this.state const addon = this.props.addons.find(addon => { return addon.name === AddonType.salt }) @@ -599,7 +737,14 @@ class KubernetesPage extends PureComponent { const saltMasterUrl = addon.url const saltMasterToken = addon.token const pParam: SaltStack = { - kwarg: {namespace: `${filterNamespace}`, detail: true}, + kwarg: { + namespace: `${filterNamespace}`, + labelselector: + !_.isEmpty(filterLabelKey) && !_.isEmpty(filterLabelValue) + ? `${filterLabelKey}=${filterLabelValue}` + : '', + detail: true, + }, } const serviceAccounts = await this.props.handleGetServiceAccounts( @@ -620,14 +765,22 @@ class KubernetesPage extends PureComponent { } public getClusterRoles = async () => { - const {selectMinion} = this.state + const {selectMinion, filterLabelKey, filterLabelValue} = this.state const addon = this.props.addons.find(addon => { return addon.name === AddonType.salt }) const saltMasterUrl = addon.url const saltMasterToken = addon.token - const pParam: SaltStack = {kwarg: {detail: true}} + const pParam: SaltStack = { + kwarg: { + labelselector: + !_.isEmpty(filterLabelKey) && !_.isEmpty(filterLabelValue) + ? `${filterLabelKey}=${filterLabelValue}` + : '', + detail: true, + }, + } const clusterRoles = await this.props.handleGetClusterRoles( saltMasterUrl, @@ -647,14 +800,22 @@ class KubernetesPage extends PureComponent { } public getClusterRoleBindings = async () => { - const {selectMinion} = this.state + const {selectMinion, filterLabelKey, filterLabelValue} = this.state const addon = this.props.addons.find(addon => { return addon.name === AddonType.salt }) const saltMasterUrl = addon.url const saltMasterToken = addon.token - const pParam: SaltStack = {kwarg: {detail: true}} + const pParam: SaltStack = { + kwarg: { + labelselector: + !_.isEmpty(filterLabelKey) && !_.isEmpty(filterLabelValue) + ? `${filterLabelKey}=${filterLabelValue}` + : '', + detail: true, + }, + } const clusterRoleBindings = await this.props.handleGetClusterRoleBindings( saltMasterUrl, @@ -674,7 +835,12 @@ class KubernetesPage extends PureComponent { } public getRoles = async () => { - const {selectMinion, filterNamespace} = this.state + const { + selectMinion, + filterNamespace, + filterLabelKey, + filterLabelValue, + } = this.state const addon = this.props.addons.find(addon => { return addon.name === AddonType.salt }) @@ -682,7 +848,14 @@ class KubernetesPage extends PureComponent { const saltMasterUrl = addon.url const saltMasterToken = addon.token const pParam: SaltStack = { - kwarg: {namespace: `${filterNamespace}`, detail: true}, + kwarg: { + namespace: `${filterNamespace}`, + labelselector: + !_.isEmpty(filterLabelKey) && !_.isEmpty(filterLabelValue) + ? `${filterLabelKey}=${filterLabelValue}` + : '', + detail: true, + }, } const roles = await this.props.handleGetRoles( @@ -703,7 +876,12 @@ class KubernetesPage extends PureComponent { } public getRoleBindings = async () => { - const {selectMinion, filterNamespace} = this.state + const { + selectMinion, + filterNamespace, + filterLabelKey, + filterLabelValue, + } = this.state const addon = this.props.addons.find(addon => { return addon.name === AddonType.salt }) @@ -711,7 +889,14 @@ class KubernetesPage extends PureComponent { const saltMasterUrl = addon.url const saltMasterToken = addon.token const pParam: SaltStack = { - kwarg: {namespace: `${filterNamespace}`, detail: true}, + kwarg: { + namespace: `${filterNamespace}`, + labelselector: + !_.isEmpty(filterLabelKey) && !_.isEmpty(filterLabelValue) + ? `${filterLabelKey}=${filterLabelValue}` + : '', + detail: true, + }, } const roleBindings = await this.props.handleGetRoleBindings( @@ -732,14 +917,22 @@ class KubernetesPage extends PureComponent { } public getPersistentVolumes = async () => { - const {selectMinion} = this.state + const {selectMinion, filterLabelKey, filterLabelValue} = this.state const addon = this.props.addons.find(addon => { return addon.name === AddonType.salt }) const saltMasterUrl = addon.url const saltMasterToken = addon.token - const pParam: SaltStack = {kwarg: {detail: true}} + const pParam: SaltStack = { + kwarg: { + labelselector: + !_.isEmpty(filterLabelKey) && !_.isEmpty(filterLabelValue) + ? `${filterLabelKey}=${filterLabelValue}` + : '', + detail: true, + }, + } const persistentVolumes = await this.props.handleGetPersistentVolumes( saltMasterUrl, @@ -759,7 +952,12 @@ class KubernetesPage extends PureComponent { } public getPersistentVolumeClaims = async () => { - const {selectMinion, filterNamespace} = this.state + const { + selectMinion, + filterNamespace, + filterLabelKey, + filterLabelValue, + } = this.state const addon = this.props.addons.find(addon => { return addon.name === AddonType.salt }) @@ -767,7 +965,14 @@ class KubernetesPage extends PureComponent { const saltMasterUrl = addon.url const saltMasterToken = addon.token const pParam: SaltStack = { - kwarg: {namespace: `${filterNamespace}`, detail: true}, + kwarg: { + namespace: `${filterNamespace}`, + labelselector: + !_.isEmpty(filterLabelKey) && !_.isEmpty(filterLabelValue) + ? `${filterLabelKey}=${filterLabelValue}` + : '', + detail: true, + }, } const persistentVolumeClaims = await this.props.handleGetPersistentVolumeClaims( @@ -955,7 +1160,7 @@ class KubernetesPage extends PureComponent { return resultJson } - public getK8sOjbect = async () => { + public getK8sObject = async () => { this.setState({remoteDataState: RemoteDataState.Loading}) const info = await Promise.all([ @@ -974,6 +1179,11 @@ class KubernetesPage extends PureComponent { this.getPersistentVolumeClaims(), ]) + if (typeof info[0] !== 'object') { + this.setState({remoteDataState: RemoteDataState.Error}) + return + } + let kubernetesData = {} const kubernetesD3Data: D3K8sData = {name: 'k8s', children: []} const d3Namespaces = {} @@ -1043,6 +1253,7 @@ class KubernetesPage extends PureComponent { name: `Namespace_${namespaceName}_Service_${serviceName}`, label: serviceName, type: 'SVC', + namespace: `${namespaceName}`, value: 10, } d3Namespaces[namespaceName].children[ @@ -1084,6 +1295,7 @@ class KubernetesPage extends PureComponent { name: `Namespace_${namespaceName}_Ingress_${ingressName}`, label: ingressName, type: 'IGS', + namespace: `${namespaceName}`, value: 10, } @@ -1126,6 +1338,7 @@ class KubernetesPage extends PureComponent { name: `Namespace_${namespaceName}_Configmap_${configmapName}`, label: configmapName, type: 'CM', + namespace: `${namespaceName}`, value: 10, } @@ -1168,6 +1381,7 @@ class KubernetesPage extends PureComponent { name: `Namespace_${namespaceName}_Secret_${secretName}`, label: secretName, type: 'SR', + namespace: `${namespaceName}`, value: 10, } @@ -1209,6 +1423,7 @@ class KubernetesPage extends PureComponent { name: `Namespace_${namespaceName}_ServiceAccount_${serviceAccountName}`, label: serviceAccountName, type: 'SA', + namespace: `${namespaceName}`, value: 10, } @@ -1332,6 +1547,7 @@ class KubernetesPage extends PureComponent { name: `Namespace_${namespaceName}_Role_${roleName}`, label: roleName, type: 'RL', + namespace: `${namespaceName}`, value: 10, } d3Namespaces[namespaceName].children[ @@ -1373,6 +1589,7 @@ class KubernetesPage extends PureComponent { name: `Namespace_${namespaceName}_RoleBinding_${roleBindingName}`, label: roleBindingName, type: 'RB', + namespace: `${namespaceName}`, value: 10, } @@ -1458,6 +1675,7 @@ class KubernetesPage extends PureComponent { name: `Namespace_${namespaceName}_PersistentVolumeClaim_${persistentVolumeClaimName}`, label: persistentVolumeClaimName, type: 'PVC', + namespace: `${namespaceName}`, value: 10, } @@ -1676,6 +1894,7 @@ class KubernetesPage extends PureComponent { child: `Namespace.${namespace}.ReplicaSet.${ownerName}.Pod`, label: ownerName, type: 'RS', + namespace: `${namespace}`, status: _.get(replicaSets[ownerName], 'status.available_replicas') !== _.get(replicaSets[ownerName], 'status.replicas') @@ -1729,6 +1948,7 @@ class KubernetesPage extends PureComponent { label: ownerName, child: `Namespace.${namespace}.Deployment.${ownerName}.Pod`, type: 'DP', + namespace: `${namespace}`, status: _.get( deployments[ownerName], @@ -1800,6 +2020,7 @@ class KubernetesPage extends PureComponent { label: name, child: `Namespace.${namespace}.Deployment.${name}.Pod`, type: 'DP', + namespace: `${namespace}`, status: _.get( deployments[ownerName], @@ -1867,6 +2088,7 @@ class KubernetesPage extends PureComponent { name: `Namespace_${namespace}_ReplicationController_${ownerName}`, label: ownerName, type: 'RC', + namespace: `${namespace}`, child: `Namespace.${namespace}.ReplicationController.${ownerName}.Pod`, status: _.get( @@ -1927,6 +2149,7 @@ class KubernetesPage extends PureComponent { name: `Namespace_${namespace}_DaemonSet_${ownerName}`, label: ownerName, type: 'DS', + namespace: `${namespace}`, child: `Namespace.${namespace}.DaemonSet.${ownerName}.Pod`, status: _.get(daemonSets[ownerName], 'status.numberUnavailable') && @@ -1985,6 +2208,7 @@ class KubernetesPage extends PureComponent { name: `Namespace_${namespace}_StatefulSet_${ownerName}`, label: ownerName, type: 'SS', + namespace: `${namespace}`, child: `Namespace.${namespace}.StatefulSet.${ownerName}.Pod`, status: _.get(statefulSets[ownerName], 'status.replicas') !== @@ -2038,6 +2262,7 @@ class KubernetesPage extends PureComponent { name: `Namespace_${namespace}_Job_${ownerName}`, label: ownerName, type: 'Job', + namespace: `${namespace}`, owner: `Namespace.${namespace}.Job.${ownerName}.metadata.owner_references`, child: `Namespace.${namespace}.Job.${ownerName}.Pod`, status: @@ -2086,6 +2311,7 @@ class KubernetesPage extends PureComponent { name: `Namespace_${namespace}_CronJob_${name}`, label: name, type: 'CJ', + namespace: `${namespace}`, child: `Namespace.${namespace}.CronJob.${name}.Pod`, status: _.get(jobs[ownerName], 'status.failed') && @@ -2147,6 +2373,7 @@ class KubernetesPage extends PureComponent { name: `Namespace_${namespace}_CronJob_${name}`, label: name, type: 'CJ', + namespace: `${namespace}`, child: `Namespace.${namespace}.CronJob.${name}.Pod`, status: _.get(jobs[ownerName], 'status.failed') && @@ -2211,6 +2438,7 @@ class KubernetesPage extends PureComponent { label: podName, owner: `Namespace.${namespace}.Node.${nodeName}.Pod.${podName}.metadata.owner_references`, type: 'Pod', + namespace: `${namespace}`, data: { cpu: `${ podCPU !== 0 @@ -2425,62 +2653,76 @@ class KubernetesPage extends PureComponent { try { _.forEach(kubernetesObject, m => { if (m['type'] === 'Node') { - const cpuUsage = - (parseFloat(m['cpu']) / - parseFloat( - node - .select(`circle[data-label=${m['name']}]`) - .attr('data-limit-cpu') - )) * - 100 - const memoryUsage = - (parseFloat(m['memory']) / - parseFloat( - node - .select(`circle[data-label=${m['name']}]`) - .attr('data-limit-memory') - )) * - 100 - - node - .select(`circle[data-label=${m['name']}]`) - .attr('data-cpu', `${cpuUsage}`) - node - .select(`circle[data-label=${m['name']}]`) - .attr('data-memory', `${memoryUsage}`) - const pick = cpuUsage > memoryUsage ? cpuUsage : memoryUsage - node - .select(`circle[data-label=${m['name']}]`) - .attr('fill', kubernetesStatusColor(pick / 100)) + if ( + _.find( + node.select(`circle[data-type=${'Node'}]`).data(), + nodeData => nodeData.data.label === m['name'] + ) + ) { + const cpuUsage = + (parseFloat(m['cpu']) / + parseFloat( + node + .select(`circle[data-label=${m['name']}]`) + .attr('data-limit-cpu') + )) * + 100 + const memoryUsage = + (parseFloat(m['memory']) / + parseFloat( + node + .select(`circle[data-label=${m['name']}]`) + .attr('data-limit-memory') + )) * + 100 + + node + .select(`circle[data-label=${m['name']}]`) + .attr('data-cpu', `${cpuUsage}`) + node + .select(`circle[data-label=${m['name']}]`) + .attr('data-memory', `${memoryUsage}`) + const pick = cpuUsage > memoryUsage ? cpuUsage : memoryUsage + node + .select(`circle[data-label=${m['name']}]`) + .attr('fill', kubernetesStatusColor(pick / 100)) + } } else { - const cpuUsage = - (parseFloat(m['cpu']) / - parseFloat( - node - .select(`path[data-label=${m['name']}]`) - .attr('data-limit-cpu') - )) * - 100 - const memoryUsage = - (parseFloat(m['memory']) / - parseFloat( - node - .select(`path[data-label=${m['name']}]`) - .attr('data-limit-memory') - )) * - 100 - - node - .select(`path[data-label=${m['name']}]`) - .attr('data-cpu', `${cpuUsage}`) - node - .select(`path[data-label=${m['name']}]`) - .attr('data-memory', `${memoryUsage}`) - - const pick = cpuUsage > memoryUsage ? cpuUsage : memoryUsage - node - .select(`path[data-label=${m['name']}]`) - .attr('fill', kubernetesStatusColor(pick / 100)) + if ( + _.find( + node.select(`path[data-type=${'Pod'}]`).data(), + podData => podData.data.label === m['name'] + ) + ) { + const cpuUsage = + (parseFloat(m['cpu']) / + parseFloat( + node + .select(`path[data-label=${m['name']}]`) + .attr('data-limit-cpu') + )) * + 100 + const memoryUsage = + (parseFloat(m['memory']) / + parseFloat( + node + .select(`path[data-label=${m['name']}]`) + .attr('data-limit-memory') + )) * + 100 + + node + .select(`path[data-label=${m['name']}]`) + .attr('data-cpu', `${cpuUsage}`) + node + .select(`path[data-label=${m['name']}]`) + .attr('data-memory', `${memoryUsage}`) + + const pick = cpuUsage > memoryUsage ? cpuUsage : memoryUsage + node + .select(`path[data-label=${m['name']}]`) + .attr('fill', kubernetesStatusColor(pick / 100)) + } } }) } catch (error) { @@ -2550,6 +2792,7 @@ class KubernetesPage extends PureComponent { const {autoRefresh, manualRefresh} = this.props const { kubernetesObject, + kubernetesData, focuseNode, selectedAutoRefresh, selectMinion, @@ -2576,6 +2819,13 @@ class KubernetesPage extends PureComponent { this.handleKubernetesResourceAutoRefresh() } + if ( + JSON.stringify(prevState.kubernetesData) !== + JSON.stringify(kubernetesData) + ) { + this.fetchK8sData() + } + if ( JSON.stringify(prevState.kubernetesObject) !== JSON.stringify(kubernetesObject) @@ -2634,7 +2884,7 @@ class KubernetesPage extends PureComponent { prevState.filterLabelValue !== filterLabelValue || prevState.filterLimit !== filterLimit ) { - this.getK8sOjbect() + this.getK8sObject() } } @@ -2687,8 +2937,8 @@ class KubernetesPage extends PureComponent { selectedLimit={selectedLimit} labelKey={labelKey} labelValue={labelValue} - namespaces={namespaces} - nodes={nodes} + namespaces={['All namespaces', ...namespaces]} + nodes={['All nodes', ...nodes]} limits={limits} height={this.height} minions={minions} @@ -2828,7 +3078,7 @@ class KubernetesPage extends PureComponent { } private handleKubernetesRefresh = async () => { - await this.getK8sOjbect() + await this.getK8sObject() } private handleKubernetesResourceRefresh = async () => { @@ -2846,7 +3096,7 @@ class KubernetesPage extends PureComponent { this.clearKubernetesObjectInterval() if (selectMinion === null || selectedAutoRefresh === 0) return - await this.getK8sOjbect() + await this.getK8sObject() this.getKubernetesObjectInterval = setTimeout(() => { this.handleKubernetesAutoRefresh() }, selectedAutoRefresh) @@ -2897,7 +3147,9 @@ class KubernetesPage extends PureComponent { } private onChooseNamespace = (namespace: {text: string}) => { - this.setState({selectedNamespace: namespace.text}) + this.setState({ + selectedNamespace: namespace.text, + }) } private onChooseNodes = (node: {text: string}) => { @@ -2931,9 +3183,10 @@ class KubernetesPage extends PureComponent { selectedLimit, } = this.state this.setState({ - filterNamespace: selectedNamespace, - filterNode: selectedNode, - filterLabelKey: labelKey, + filterNamespace: + selectedNamespace !== 'All namespaces' ? selectedNamespace : '', + filterNode: selectedNode !== 'All nodes' ? selectedNode : '', + filterLabelKey: labelKey !== 'Unlimited' ? labelKey : '', filterLabelValue: labelValue, filterLimit: selectedLimit, }) @@ -2943,10 +3196,139 @@ class KubernetesPage extends PureComponent { console.log('onClick Pod Name') } - private onClickVisualizePod = (target: SVGSVGElement): void => { - const focuseNodeName = d3.select(target).attr('data-name') - const focuseNodeLabel = d3.select(target).attr('data-label') - const focuseNodeType = d3.select(target).attr('data-type') + private onClickVisualizePod = async (data: any) => { + const {selectMinion} = this.state + const focuseNodeName = _.get(data, 'data.name') + const focuseNodeLabel = _.get(data, 'data.label') + const focuseNodeType = _.get(data, 'data.type') + const focuseNamespace = _.get(data, 'data.namespace') + + const addon = this.props.addons.find(addon => { + return addon.name === AddonType.salt + }) + + const saltMasterUrl = addon.url + const saltMasterToken = addon.token + let pParam: SaltStack = {} + + if (focuseNodeType === 'Namespace') + pParam = { + fun: 'kubernetes.show_namespace', + kwarg: {name: focuseNodeLabel}, + } + else if (focuseNodeType === 'Node') + pParam = {fun: 'kubernetes.node', kwarg: {name: focuseNodeLabel}} + else if (focuseNodeType === 'Pod') + pParam = { + fun: 'kubernetes.show_pod', + kwarg: {namespace: focuseNamespace, name: focuseNodeLabel}, + } + else if (focuseNodeType === 'DP') + pParam = { + fun: 'kubernetes.show_deployment', + kwarg: {namespace: focuseNamespace, name: focuseNodeLabel}, + } + else if (focuseNodeType === 'RS') + pParam = { + fun: 'show_replica_set', + kwarg: {namespace: focuseNamespace, name: focuseNodeLabel}, + } + else if (focuseNodeType === 'RC') + pParam = { + fun: 'kubernetes.show_replication_controller', + kwarg: {namespace: focuseNamespace, name: focuseNodeLabel}, + } + else if (focuseNodeType === 'DS') + pParam = { + fun: 'kubernetes.show_daemon_set', + kwarg: {namespace: focuseNamespace, name: focuseNodeLabel}, + } + else if (focuseNodeType === 'SS') + pParam = { + fun: 'kubernetes.show_stateful_set', + kwarg: {namespace: focuseNamespace, name: focuseNodeLabel}, + } + else if (focuseNodeType === 'Job') + pParam = { + fun: 'kubernetes.show_job', + kwarg: {namespace: focuseNamespace, name: focuseNodeLabel}, + } + else if (focuseNodeType === 'CJ') + pParam = { + fun: 'kubernetes.show_cron_job', + kwarg: {namespace: focuseNamespace, name: focuseNodeLabel}, + } + else if (focuseNodeType === 'SVC') + pParam = { + fun: 'kubernetes.show_service', + kwarg: {namespace: focuseNamespace, name: focuseNodeLabel}, + } + else if (focuseNodeType === 'IGS') + pParam = { + fun: 'kubernetes.show_ingress', + kwarg: {namespace: focuseNamespace, name: focuseNodeLabel}, + } + else if (focuseNodeType === 'CM') + pParam = { + fun: 'kubernetes.show_configmap', + kwarg: {namespace: focuseNamespace, name: focuseNodeLabel}, + } + else if (focuseNodeType === 'SR') + pParam = { + fun: 'kubernetes.show_secret', + kwarg: {namespace: focuseNamespace, name: focuseNodeLabel}, + } + else if (focuseNodeType === 'SA') + pParam = { + fun: 'kubernetes.show_service_account', + kwarg: {namespace: focuseNamespace, name: focuseNodeLabel}, + } + else if (focuseNodeType === 'CR') + pParam = { + fun: 'kubernetes.show_cluster_role', + kwarg: {name: focuseNodeLabel}, + } + else if (focuseNodeType === 'CRB') + pParam = { + fun: 'kubernetes.show_cluster_role_binding', + kwarg: {name: focuseNodeLabel}, + } + else if (focuseNodeType === 'RL') + pParam = { + fun: 'kubernetes.show_role', + kwarg: {namespace: focuseNamespace, name: focuseNodeLabel}, + } + else if (focuseNodeType === 'RB') + pParam = { + fun: 'kubernetes.show_role_binding', + kwarg: {namespace: focuseNamespace, name: focuseNodeLabel}, + } + else if (focuseNodeType === 'PV') + pParam = { + fun: 'kubernetes.show_persistent_volume', + kwarg: {name: focuseNodeLabel}, + } + else if (focuseNodeType === 'PVC') + pParam = { + fun: 'kubernetes.show_persistent_volume_claim', + kwarg: {namespace: focuseNamespace, name: focuseNodeLabel}, + } + + if (_.isEmpty(pParam)) return + + const k8sDetail = await this.props.handleGetK8sDetail( + saltMasterUrl, + saltMasterToken, + selectMinion, + pParam + ) + + const resultJson = JSON.parse( + JSON.stringify( + _.values(yaml.safeLoad(k8sDetail.data).return[0])[0], + this.jsonRemoveNull + ) + ) if (focuseNodeName) { this.setState({ @@ -2955,6 +3337,7 @@ class KubernetesPage extends PureComponent { label: focuseNodeLabel, type: focuseNodeType, }, + script: resultJson, }) } } @@ -3040,6 +3423,7 @@ const mdtp = { handleGetRoleBindings: getLocalK8sRoleBindingsAsync, handleGetPersistentVolumes: getLocalK8sPersistentVolumesAsync, handleGetPersistentVolumeClaims: getLocalK8sPersistentVolumeClaimsAsync, + handleGetK8sDetail: getLocalK8sDetailAsync, notify: notifyAction, } diff --git a/frontend/src/hosts/types/kubernetes.ts b/frontend/src/hosts/types/kubernetes.ts index b0b4dfbe..d6746206 100644 --- a/frontend/src/hosts/types/kubernetes.ts +++ b/frontend/src/hosts/types/kubernetes.ts @@ -28,6 +28,7 @@ export interface D3DataDepth3 { type: string value: number owner?: string + namespace?: string } export interface Kubernetes { @@ -190,4 +191,10 @@ export interface KubernetesProps { targetMinion: string, pParam?: SaltStack ) => Promise + handleGetK8sDetail: ( + saltMasterUrl: string, + saltMasterToken: string, + targetMinion: string, + pParam?: SaltStack + ) => Promise } diff --git a/frontend/src/shared/apis/saltStack.ts b/frontend/src/shared/apis/saltStack.ts index 0308bfbd..66c52828 100644 --- a/frontend/src/shared/apis/saltStack.ts +++ b/frontend/src/shared/apis/saltStack.ts @@ -45,6 +45,7 @@ interface Params { namespace?: any fieldselector?: any labelselector?: any + limit?: number } username?: string password?: string @@ -987,6 +988,11 @@ export async function getLocalK8sPods( ? pParam.kwarg.detail : false : false, + limit: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('limit') + ? pParam.kwarg.limit + : null + : null, }, } return await apiRequest(pUrl, pToken, params, 'application/x-yaml') @@ -1015,6 +1021,11 @@ export async function getLocalK8sDeployments( ? pParam.kwarg.namespace : '' : '', + labelselector: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('labelselector') + ? pParam.kwarg.labelselector + : '' + : '', detail: pParam.hasOwnProperty('kwarg') ? pParam.kwarg.hasOwnProperty('detail') ? pParam.kwarg.detail @@ -1048,6 +1059,11 @@ export async function getLocalK8sReplicaSets( ? pParam.kwarg.namespace : '' : '', + labelselector: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('labelselector') + ? pParam.kwarg.labelselector + : '' + : '', detail: pParam.hasOwnProperty('kwarg') ? pParam.kwarg.hasOwnProperty('detail') ? pParam.kwarg.detail @@ -1081,6 +1097,11 @@ export async function getLocalK8sReplicationControllers( ? pParam.kwarg.namespace : '' : '', + labelselector: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('labelselector') + ? pParam.kwarg.labelselector + : '' + : '', detail: pParam.hasOwnProperty('kwarg') ? pParam.kwarg.hasOwnProperty('detail') ? pParam.kwarg.detail @@ -1151,6 +1172,11 @@ export async function getLocalK8sDaemonSets( ? pParam.kwarg.namespace : '' : '', + labelselector: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('labelselector') + ? pParam.kwarg.labelselector + : '' + : '', detail: pParam.hasOwnProperty('kwarg') ? pParam.kwarg.hasOwnProperty('detail') ? pParam.kwarg.detail @@ -1184,6 +1210,11 @@ export async function getLocalK8sStatefulSets( ? pParam.kwarg.namespace : '' : '', + labelselector: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('labelselector') + ? pParam.kwarg.labelselector + : '' + : '', detail: pParam.hasOwnProperty('kwarg') ? pParam.kwarg.hasOwnProperty('detail') ? pParam.kwarg.detail @@ -1217,6 +1248,11 @@ export async function getLocalK8sJobs( ? pParam.kwarg.namespace : '' : '', + labelselector: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('labelselector') + ? pParam.kwarg.labelselector + : '' + : '', detail: pParam.hasOwnProperty('kwarg') ? pParam.kwarg.hasOwnProperty('detail') ? pParam.kwarg.detail @@ -1278,6 +1314,11 @@ export async function getLocalK8sCronJobs( ? pParam.kwarg.namespace : '' : '', + labelselector: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('labelselector') + ? pParam.kwarg.labelselector + : '' + : '', detail: pParam.hasOwnProperty('kwarg') ? pParam.kwarg.hasOwnProperty('detail') ? pParam.kwarg.detail @@ -1311,6 +1352,11 @@ export async function getLocalK8sServices( ? pParam.kwarg.namespace : '' : '', + labelselector: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('labelselector') + ? pParam.kwarg.labelselector + : '' + : '', detail: pParam.hasOwnProperty('kwarg') ? pParam.kwarg.hasOwnProperty('detail') ? pParam.kwarg.detail @@ -1344,6 +1390,11 @@ export async function getLocalK8sIngresses( ? pParam.kwarg.namespace : '' : '', + labelselector: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('labelselector') + ? pParam.kwarg.labelselector + : '' + : '', detail: pParam.hasOwnProperty('kwarg') ? pParam.kwarg.hasOwnProperty('detail') ? pParam.kwarg.detail @@ -1377,6 +1428,11 @@ export async function getLocalK8sConfigmaps( ? pParam.kwarg.namespace : '' : '', + labelselector: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('labelselector') + ? pParam.kwarg.labelselector + : '' + : '', detail: pParam.hasOwnProperty('kwarg') ? pParam.kwarg.hasOwnProperty('detail') ? pParam.kwarg.detail @@ -1444,6 +1500,11 @@ export async function getLocalK8sSecrets( ? pParam.kwarg.namespace : '' : '', + labelselector: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('labelselector') + ? pParam.kwarg.labelselector + : '' + : '', detail: pParam.hasOwnProperty('kwarg') ? pParam.kwarg.hasOwnProperty('detail') ? pParam.kwarg.detail @@ -1477,6 +1538,11 @@ export async function getLocalK8sServiceAccounts( ? pParam.kwarg.namespace : '' : '', + labelselector: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('labelselector') + ? pParam.kwarg.labelselector + : '' + : '', detail: pParam.hasOwnProperty('kwarg') ? pParam.kwarg.hasOwnProperty('detail') ? pParam.kwarg.detail @@ -1505,6 +1571,11 @@ export async function getLocalK8sClusterRoles( fun: 'kubernetes.cluster_roles', tgt: pMinionId, kwarg: { + labelselector: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('labelselector') + ? pParam.kwarg.labelselector + : '' + : '', detail: pParam.hasOwnProperty('kwarg') ? pParam.kwarg.hasOwnProperty('detail') ? pParam.kwarg.detail @@ -1563,6 +1634,11 @@ export async function getLocalK8sClusterRoleBindings( fun: 'kubernetes.cluster_role_bindings', tgt: pMinionId, kwarg: { + labelselector: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('labelselector') + ? pParam.kwarg.labelselector + : '' + : '', detail: pParam.hasOwnProperty('kwarg') ? pParam.kwarg.hasOwnProperty('detail') ? pParam.kwarg.detail @@ -1596,6 +1672,11 @@ export async function getLocalK8sRoles( ? pParam.kwarg.namespace : '' : '', + labelselector: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('labelselector') + ? pParam.kwarg.labelselector + : '' + : '', detail: pParam.hasOwnProperty('kwarg') ? pParam.kwarg.hasOwnProperty('detail') ? pParam.kwarg.detail @@ -1629,6 +1710,11 @@ export async function getLocalK8sRoleBindings( ? pParam.kwarg.namespace : '' : '', + labelselector: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('labelselector') + ? pParam.kwarg.labelselector + : '' + : '', detail: pParam.hasOwnProperty('kwarg') ? pParam.kwarg.hasOwnProperty('detail') ? pParam.kwarg.detail @@ -1687,6 +1773,11 @@ export async function getLocalK8sPersistentVolumes( fun: 'kubernetes.persistent_volumes', tgt: pMinionId, kwarg: { + labelselector: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('labelselector') + ? pParam.kwarg.labelselector + : '' + : '', detail: pParam.hasOwnProperty('kwarg') ? pParam.kwarg.hasOwnProperty('detail') ? pParam.kwarg.detail @@ -1746,6 +1837,11 @@ export async function getLocalK8sPersistentVolumeClaims( fun: 'kubernetes.persistent_volume_claims', tgt: pMinionId, kwarg: { + labelselector: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('labelselector') + ? pParam.kwarg.labelselector + : '' + : '', detail: pParam.hasOwnProperty('kwarg') ? pParam.kwarg.hasOwnProperty('detail') ? pParam.kwarg.detail @@ -1760,6 +1856,39 @@ export async function getLocalK8sPersistentVolumeClaims( } } +export async function getLocalK8sDetail( + pUrl: string, + pToken: string, + pMinionId: string, + pParam: Params +) { + try { + const params = { + token: pToken, + eauth: 'pam', + client: 'local', + fun: pParam.fun, + tgt: pMinionId, + kwarg: { + namespace: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('namespace') + ? pParam.kwarg.namespace + : '' + : '', + name: pParam.hasOwnProperty('kwarg') + ? pParam.kwarg.hasOwnProperty('name') + ? pParam.kwarg.name + : '' + : '', + }, + } + return await apiRequest(pUrl, pToken, params, 'application/x-yaml') + } catch (error) { + console.error(error) + throw error + } +} + const saltActivityLog = async ( activity: object, result: object