def gen_used_info(host: Dict, all_cluster_nodes: Dict, project_cluster_info: Dict) -> Dict: """ 生成主机被使用的项目,集群信息 :param host: 原始主机信息 :param all_cluster_nodes: 全集群节点信息 :param project_cluster_info: 项目 & 集群信息 :return: 主机的使用信息 """ info = { 'project_name': '', 'cluster_name': '', 'cluster_id': '', 'is_used': False } for ip in host['bk_host_innerip'].split(','): node_info = all_cluster_nodes.get(ip) if not node_info: continue info['is_used'] = True info['cluster_id'] = node_info.get('cluster_id') name_dict = project_cluster_info.get(info['cluster_id']) or {} info['project_name'] = get_with_placeholder(name_dict, 'project_name') info['cluster_name'] = get_with_placeholder(name_dict, 'cluster_name') break return info
def build(self) -> Dict: """ 构造展示用的容器详情信息 """ for cs in getitems(self.pod, 'status.containerStatuses', []): if self.container_name == cs['name']: container_status = cs break else: raise ResourceNotExist( _('容器 {} 状态信息不存在').format(self.container_name)) labels = getitems(self.pod, 'metadata.labels', {}) spec, status = self.pod['spec'], self.pod['status'] for csp in spec.get('containers', []): if self.container_name == csp['name']: container_spec = csp break else: raise ResourceNotExist( _('容器 {} 模板(Spec)信息不存在').format(self.container_name)) return { 'host_name': get_with_placeholder(spec, 'nodeName'), 'host_ip': get_with_placeholder(status, 'hostIP'), 'container_ip': get_with_placeholder(status, 'podIP'), 'container_id': self._extract_container_id( get_with_placeholder(container_status, 'containerID')), 'container_name': self.container_name, 'image': get_with_placeholder(container_status, 'image'), 'network_mode': get_with_placeholder(spec, 'dnsPolicy'), # 端口映射 'ports': container_spec.get('ports', []), # 命令 'command': { 'command': get_with_placeholder(container_spec, 'command', ''), 'args': ' '.join(container_spec.get('args', [])), }, # 挂载卷 'volumes': [{ 'host_path': get_with_placeholder(mount, 'name'), 'mount_path': get_with_placeholder(mount, 'mountPath'), 'readonly': get_with_placeholder(mount, 'readOnly'), } for mount in container_spec.get('volumeMounts', [])], # 标签 'labels': [{ 'key': key, 'val': val } for key, val in labels.items()], # 资源限制 'resources': container_spec.get('resources', {}), }
def parse_v1beta1_rules(self, resource_dict: Dict) -> List: """ 解析 extensions/v1beta1 版本 Ingress Rules """ rules = [] for r in getitems(resource_dict, 'spec.rules', []): sub_rules = [ { 'host': get_with_placeholder(r, 'host'), 'path': get_with_placeholder(p, 'path'), 'serviceName': get_with_placeholder(p, 'backend.serviceName'), 'port': get_with_placeholder(p, 'backend.servicePort'), } for p in getitems(r, 'http.paths', []) ] rules.extend(sub_rules) return rules
def build_list(self) -> List[Dict]: """ 构造列表展示的容器信息 """ containers = [] for cs in getitems(self.pod, 'status.containerStatuses', []): status = message = reason = None # state 有且只有一对键值:running / terminated / waiting # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#containerstate-v1-core for k, v in cs['state'].items(): status = k message = v.get('message') or k reason = v.get('reason') or k containers.append({ # 原格式:docker://[a-zA-Z0-9]{64},需要去除前缀,特殊状态下可能不存在 'container_id': self._extract_container_id( get_with_placeholder(cs, 'containerID')), 'image': cs['image'], 'name': cs['name'], 'status': status, 'message': message, 'reason': reason, }) return containers
def parse_v1_rules(self, resource_dict: Dict) -> List: """ 解析 networking.k8s.io/v1 版本 Ingress Rules """ rules = [] for r in getitems(resource_dict, 'spec.rules', []): sub_rules = [ { 'host': get_with_placeholder(r, 'host'), 'path': get_with_placeholder(p, 'path'), 'pathType': get_with_placeholder(p, 'pathType'), 'serviceName': get_with_placeholder(p, 'backend.service.name'), 'port': get_with_placeholder(p, 'backend.service.port.number'), } for p in getitems(r, 'http.paths', []) ] rules.extend(sub_rules) return rules
def format_dict(self, resource_dict: Dict) -> Dict: res = self.format_common_dict(resource_dict) ref = resource_dict['spec']['scaleTargetRef'] res.update({ 'reference': f"{ref['kind']}/{ref['name']}", 'targets': HPAMetricsParser(resource_dict).parse(), 'min_pods': get_with_placeholder(resource_dict, 'spec.minReplicas', '<unset>'), 'max_pods': getitems(resource_dict, 'spec.maxReplicas'), 'replicas': get_with_placeholder(resource_dict, 'status.currentReplicas'), }) return res
def test_get_with_placeholder(items, expired): assert get_with_placeholder(DICT_OBJ, items) == expired