github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ui/src/util/localities.ts (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 import _ from "lodash"; 12 13 import { LocalityTier, LocalityTree } from "src/redux/localities"; 14 import { INodeStatus } from "src/util/proto"; 15 16 /* 17 * parseLocalityRoute parses the URL fragment used to route to a particular 18 * locality and returns the locality tiers it represents. 19 */ 20 export function parseLocalityRoute(route: string): LocalityTier[] { 21 if (_.isEmpty(route)) { 22 return []; 23 } 24 25 const segments = route.split("/"); 26 return segments.map((segment) => { 27 const [key, value] = segment.split("="); 28 return { key, value }; 29 }); 30 } 31 32 /* 33 * generateLocalityRoute generates the URL fragment to route to a particular 34 * locality from the locality tiers. 35 */ 36 export function generateLocalityRoute(tiers: LocalityTier[]): string { 37 return "/" + tiers.map(({ key, value }) => key + "=" + value).join("/"); 38 } 39 40 /* 41 * getNodeLocalityTiers returns the locality tiers of a node, typed as an array 42 * of LocalityTier rather than Tier$Properties. 43 */ 44 export function getNodeLocalityTiers(node: INodeStatus): LocalityTier[] { 45 return node.desc.locality.tiers.map(({ key, value }) => ({ key, value })); 46 } 47 48 /* 49 * getChildLocalities returns an array of the locality trees for localities that 50 * are the immediate children of this one. 51 */ 52 export function getChildLocalities(locality: LocalityTree): LocalityTree[] { 53 const children: LocalityTree[] = []; 54 55 _.values(locality.localities).forEach((tier) => { 56 children.push(..._.values(tier)); 57 }); 58 59 return children; 60 } 61 62 /* 63 * getLocality gets the locality within this tree which corresponds to a set of 64 * locality tiers, or null if the locality is not present. 65 */ 66 export function getLocality(localityTree: LocalityTree, tiers: LocalityTier[]): LocalityTree { 67 let result = localityTree; 68 for (let i = 0; i < tiers.length; i += 1) { 69 const { key, value } = tiers[i]; 70 71 const thisTier = result.localities[key]; 72 if (_.isNil(thisTier)) { 73 return null; 74 } 75 76 result = thisTier[value]; 77 if (_.isNil(result)) { 78 return null; 79 } 80 } 81 82 return result; 83 } 84 85 /* getLeaves returns the leaves under the given locality tree. Confusingly, 86 * in this tree the "leaves" of the tree are nodes, i.e. servers. 87 */ 88 export function getLeaves(tree: LocalityTree): INodeStatus[] { 89 const output: INodeStatus[] = []; 90 function recur(curTree: LocalityTree) { 91 output.push(...curTree.nodes); 92 _.forEach(curTree.localities, (localityValues) => { 93 _.forEach(localityValues, recur); 94 }); 95 } 96 recur(tree); 97 return output; 98 } 99 100 /* 101 * getLocalityLabel returns the human-readable label for the locality. 102 */ 103 export function getLocalityLabel(path: LocalityTier[]): string { 104 if (path.length === 0) { 105 return "Cluster"; 106 } 107 108 const thisTier = path[path.length - 1]; 109 return `${thisTier.key}=${thisTier.value}`; 110 } 111 112 /* 113 * allNodesHaveLocality returns true if there exists a node without a locality flag. 114 */ 115 export function allNodesHaveLocality(nodes: INodeStatus[]): boolean { 116 const nodesWithoutLocality = nodes.filter((n) => n.desc.locality.tiers.length === 0); 117 return nodesWithoutLocality.length === 0; 118 }