-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
331 additions
and
203 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module.exports = (stream) => { | ||
const chunks = [] | ||
return new Promise((resolve, reject) => { | ||
stream.on("data", (chunk) => chunks.push(Buffer.from(chunk))) | ||
stream.on("error", (err) => reject(err)) | ||
stream.on("end", () => resolve(Buffer.concat(chunks).toString("utf8"))) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
207 changes: 207 additions & 0 deletions
207
packages/kontinuous/src/build/infos/component-tree-infos.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
// const fs = require("fs-extra") | ||
|
||
const ctx = require("~/ctx") | ||
const logTree = require("~common/utils/log-tree") | ||
|
||
const getTreeInfos = {} | ||
|
||
getTreeInfos.Namespace = (resource) => { | ||
const { manifest } = resource | ||
return [{ name: `name: ${manifest.metadata.name}`}] | ||
} | ||
|
||
getTreeInfos.Ingress = (resource)=>{ | ||
const { manifest } = resource | ||
const redirect = manifest.metadata?.annotations["nginx.ingress.kubernetes.io/permanent-redirect"] | ||
return [...(manifest.spec?.rules ? [{ | ||
name: "hosts", | ||
children: manifest.spec.rules.map(({host})=>({name:`https://${host}`})) | ||
}] : []), ...(redirect ? [{ | ||
name: "redirect", | ||
children: [{name: redirect}] | ||
}] : [])] | ||
} | ||
|
||
getTreeInfos.Deployment = (resource) => { | ||
const { manifest } = resource | ||
const containers = manifest.spec?.template?.spec?.containers | ||
const initContainers = manifest.spec?.template?.spec?.initContainers | ||
return [...(containers ? containers.map(container=>{ | ||
return {name:container.name, children: [ | ||
{ | ||
name: `image: ${container.image}`, | ||
}, | ||
{ | ||
name: `port${container.ports.length>1?"s":""}: ${container.ports.map(({ containerPort }) => containerPort).join(",")}`, | ||
}, | ||
]}}) : []), | ||
...(initContainers ? initContainers.map(container=>{ | ||
return {name: `${container.name} (init)`, children: [ | ||
{ | ||
name: `image: ${container.image}`, | ||
}, | ||
]}}) : []), | ||
] | ||
} | ||
|
||
getTreeInfos.Service = (resource) => { | ||
const { manifest } = resource | ||
const ports = manifest.spec.ports | ||
const children = [] | ||
if(ports){ | ||
const portStr = ports.map(port=> `${port.name ? port.name + "=" : ""}${port.port}:${port.targetPort}`) | ||
children.push({ | ||
name: `port${ports.length > 1 ? "s" : ""}: ${portStr}` | ||
}) | ||
} | ||
return children | ||
} | ||
|
||
getTreeInfos.ConfigMap = (resource) => { | ||
const { manifest } = resource | ||
return [{ name: `name: ${manifest.metadata.name}` }] | ||
} | ||
|
||
getTreeInfos.SealedSecret = (resource) => { | ||
const { manifest } = resource | ||
return [{ name: `name: ${manifest.metadata.name}` }] | ||
} | ||
|
||
getTreeInfos.Job = (resource) => { | ||
const { manifest } = resource | ||
const containers = manifest.spec?.template?.spec?.containers | ||
const initContainers = manifest.spec?.template?.spec?.initContainers | ||
return [...(containers ? containers.map(container => { | ||
return { | ||
name: container.name, children: [ | ||
{ | ||
name: `image: ${container.image}`, | ||
}, | ||
] | ||
} | ||
}) : []), | ||
...(initContainers ? initContainers.map(container => { | ||
return { | ||
name: `${container.name} (init)`, children: [ | ||
{ | ||
name: `image: ${container.image}`, | ||
}, | ||
] | ||
} | ||
}) : []), | ||
] | ||
} | ||
|
||
getTreeInfos.CronJob = (resource) => { | ||
const { manifest } = resource | ||
const containers = manifest.spec?.jobTemplate?.spec?.template?.spec?.containers | ||
const initContainers = manifest.spec?.jobTemplate?.spec?.template?.spec?.initContainers | ||
return [ | ||
{ name: `schedule: ${manifest.spec.schedule}` }, | ||
...(containers ? containers.map(container => { | ||
return { | ||
name: container.name, children: [ | ||
{ | ||
name: `image: ${container.image}`, | ||
}, | ||
] | ||
} | ||
}) : []), | ||
...(initContainers ? initContainers.map(container => { | ||
return { | ||
name: `${container.name} (init)`, children: [ | ||
{ | ||
name: `image: ${container.image}`, | ||
}, | ||
] | ||
} | ||
}) : []), | ||
] | ||
} | ||
|
||
|
||
module.exports = async(manifests)=>{ | ||
const logger = ctx.require("logger") | ||
const config = ctx.require("config") | ||
const { | ||
buildPath, | ||
} = config | ||
|
||
const componentResources = {} | ||
const globalResources = {kinds: {}} | ||
for (let manifest of manifests) { | ||
if (!manifest.metadata?.labels?.component) { | ||
if (!globalResources.kinds[manifest.kind]) { | ||
globalResources.kinds[manifest.kind] = [] | ||
} | ||
globalResources.kinds[manifest.kind].push({ | ||
name: manifest.metadata?.name, | ||
manifest, | ||
}) | ||
} else { | ||
const { component } = manifest.metadata.labels | ||
if (!componentResources[component]){ | ||
componentResources[component] = { | ||
kinds: {} | ||
} | ||
} | ||
if (!componentResources[component].kinds[manifest.kind]){ | ||
componentResources[component].kinds[manifest.kind] = [] | ||
} | ||
componentResources[component].kinds[manifest.kind].push({ | ||
name: manifest.metadata?.name, | ||
manifest, | ||
}) | ||
} | ||
} | ||
const componentsTree = [] | ||
for (const [name, component] of Object.entries(componentResources)){ | ||
const resources = [] | ||
for (const [kind, kindResources] of Object.entries(component.kinds)){ | ||
const children = [] | ||
for (const resource of kindResources){ | ||
if (getTreeInfos[kind]){ | ||
children.push(...getTreeInfos[kind](resource)) | ||
} | ||
} | ||
resources.push({ | ||
name: `${kind}`, | ||
children, | ||
}) | ||
} | ||
componentsTree.push({ | ||
name, | ||
children: resources, | ||
}) | ||
} | ||
|
||
const globalsTree = [] | ||
for (const [kind, kindResources] of Object.entries(globalResources.kinds)) { | ||
const children = [] | ||
for (const resource of kindResources) { | ||
if (getTreeInfos[kind]) { | ||
children.push(...getTreeInfos[kind](resource)) | ||
} | ||
} | ||
globalsTree.push({ | ||
name: `${kind}`, | ||
children, | ||
}) | ||
} | ||
const tree = [ | ||
{ | ||
name: "components", | ||
children: componentsTree | ||
}, | ||
{ | ||
name: "globals", | ||
children: globalsTree, | ||
}, | ||
] | ||
|
||
const treeStr = logTree(tree) | ||
logger.debug("\n"+treeStr) | ||
|
||
// await fs.writeFile(`${buildPath}/manifests.tree.md`, `\`\`\`\n${treeStr}\n\`\`\``) | ||
|
||
} |
67 changes: 67 additions & 0 deletions
67
packages/kontinuous/src/build/infos/dependencies-tree-infos.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// const fs = require("fs-extra") | ||
const plantuml = require("node-plantuml") | ||
const camelcase = require("lodash.camelcase") | ||
const ctx = require("~/ctx") | ||
|
||
const streamToString = require("~common/utils/stream-to-string") | ||
|
||
const changeGroupPrefix = "kapp.k14s.io/change-group" | ||
const changeRulePrefix = "kapp.k14s.io/change-rule" | ||
const changeRuleValuePrefix = "upsert after upserting kontinuous/" | ||
|
||
module.exports = async(manifests)=>{ | ||
const logger = ctx.require("logger") | ||
// const config = ctx.require("config") | ||
|
||
const flatDependencies = {} | ||
|
||
for (const manifest of manifests) { | ||
const annotations = manifest.metadata?.annotations | ||
if (!annotations || !annotations[changeGroupPrefix]) { | ||
continue | ||
} | ||
const depKey = Object.keys(annotations) | ||
.find(key => key.startsWith(`${changeGroupPrefix}.`)) | ||
.split(".").pop() | ||
|
||
for (const [key, value] of Object.entries(annotations)) { | ||
if ( | ||
(key === changeRulePrefix || | ||
key.startsWith(`${changeRulePrefix}.`)) | ||
&& value.startsWith(changeRuleValuePrefix) | ||
) { | ||
if(!flatDependencies[depKey]){ | ||
flatDependencies[depKey] = new Set() | ||
} | ||
let dep = value.slice(changeRuleValuePrefix.length) | ||
dep = dep.split(".").shift() | ||
dep = camelcase(dep) | ||
flatDependencies[depKey].add(dep) | ||
} | ||
} | ||
} | ||
|
||
|
||
const uml = [] | ||
for(const [key, dependenciesSet] of Object.entries(flatDependencies)){ | ||
for(const dep of dependenciesSet){ | ||
if(dep!==key){ | ||
uml.push(`${dep} -> ${key}`) | ||
} | ||
} | ||
} | ||
|
||
if(uml.length===0){ | ||
return | ||
} | ||
|
||
const gen = plantuml.generate(uml.join("\n"), { | ||
format: "ascii" | ||
}); | ||
const result = await streamToString(gen.out) | ||
logger.debug("\n"+result) | ||
|
||
// await fs.writeFile(`${config.buildPath}/dependencies.tree.md`, `uml\`\`\`\n${result}\n\`\`\``) | ||
|
||
|
||
} |
Oops, something went wrong.