Skip to content

Instantly share code, notes, and snippets.

@Eccenux
Last active August 9, 2024 09:33
Show Gist options
  • Save Eccenux/7aa2a4289d1e174f6d8d64aab34a045c to your computer and use it in GitHub Desktop.
Save Eccenux/7aa2a4289d1e174f6d8d64aab34a045c to your computer and use it in GitHub Desktop.
Proxmox multitags
// First copy and setup this token
// Use any api call to fgind the correct value (also GET calls)
// (CSRFPreventionToken header)
reqToken = '6a...'
// then paste `ProxTagger.js`
// read all nodes
nodes = await ProxTagger.readNodes();
// check structure of a node
console.log(nodes[0]);
// example filter
data = nodes
.filter(n=>n.name.search(/^(sm-|db00[0-9])/) >= 0) // include nodes starting with "sm-" and "db000..9"
.filter(n=>n.name.search(/^(sm-rel)/) < 0) // exclude nodes starting with "sm-rel"
.filter(n=>n.vmid < 3000) // include nodes with ID lower then 3k
.map(n=>ProxTagger.mapData(n)) // map to structure with node path, name and tags
;
// short info on filtered data set
console.log(data.map(v=>v.name + '; ' + v.path).join('\n'))
// choose this wisely (might not be easy to undo)
/*
// append tag
// (this only appends when a tag is missing, so will not cause duplicates)
ProxTagger.tagMany(data, "postgres")
// append tags
ProxTagger.tagMany(data, ["postgres", "dwh"])
// replace all tags with one
ProxTagger.tagMany(data, "postgres", true)
*/
// rename tag (in all nodes that have the tag)
// (this will read nodes having this tag and send rename requests)
ProxTagger.renameTag("priority0", '0-priority')
/**
Tagging helper for Proxmox 7+.
Filter network in FF:
-method:GET
Append tags:
```
nodes = await ProxTagger.readNodes();
// filter
data = nodes
.filter(n=>n.name.search(/^(db00[0-9]|sm-)/) >= 0)
.filter(n=>n.name.search(/^(sm-rel)/) < 0)
.map(n=>ProxTagger.mapData(n))
;
ProxTagger.tagMany(data, "postgres")
```
*/
ProxTagger = class {
/** Tag multiple nodes (defaults to appending tag(s)). */
static async tagMany(data, tagsRaw, replace) {
let res = [];
let tags = Array.isArray(tagsRaw) ? tagsRaw : [tagsRaw];
for (let d of data) {
console.log(d);
let allTags = new Set(replace ? tags : [...tags, ...d.tags]);
let re = this.tagNode(d.path, Array.from(allTags));
res.push(re);
}
await Promise.all(res);
}
static async tagRemove(data, tagsDel_, tagsAdd_) {
let res = [];
let tagsDel = Array.isArray(tagsDel_) ? tagsDel_ : [tagsDel_];
let tagsAdd = Array.isArray(tagsAdd_) ? tagsAdd_ : (tagsAdd_ ? [tagsAdd_] : []);
for (let d of data) {
console.log(d, d.tags.join());
let allTags = d.tags.filter(t => tagsDel.indexOf(t) < 0);
if (tagsAdd.length) {
allTags = Array.from(new Set([...allTags, ...tagsAdd]));
}
//console.log({was:d.tags.join(), is:allTags.join()})
let re = this.tagNode(d.path, Array.from(allTags));
//let re = Promise.resolve('done');
res.push(re);
}
await Promise.all(res);
}
/** Tag given node. */
static async tagNode(nodePath, tagsArray) {
// nodePath = 'prox001/lxc/123'
// tags = 'abc,def'
let tags = tagsArray.join(",");
await fetch(`/api2/extjs/nodes/${nodePath}/config`, {
"credentials": "include",
"headers": {
"Accept": "*/*",
"Accept-Language": "pl,en-US;q=0.7,en;q=0.3",
"CSRFPreventionToken": reqToken,
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"Pragma": "no-cache",
"Cache-Control": "no-cache"
},
"body": `tags=${encodeURIComponent(tags)}`,
"method": "PUT",
"mode": "cors"
});
}
/** Read all nodes data. */
static async readNodes() {
let re = await fetch("/api2/json/cluster/resources", {
"credentials": "include",
"headers": {
"Pragma": "no-cache",
"Cache-Control": "no-cache"
},
"method": "GET",
});
let d = await re.json();
// normalize
let data = d.data
.filter(n => 'name' in n)
.map(n => {
let tags = ('tags' in n) ? n.tags : '';
tags = tags.split(';');
n.tags = tags;
return n;
});
return data;
}
/** Map node data for tagging (after filters) */
static mapData(n) {
return ({
path: `${n.node}/${n.id}`,
name: n.name,
tags: n.tags
});
}
/** rename tag to a different tag */
static async renameTag(from, to) {
var nodes = await ProxTagger.readNodes();
console.log(nodes);
// preapre paths
var data = nodes
.filter(n => n.tags.indexOf(from) >= 0)
.map(n => ProxTagger.mapData(n));
console.log(data, from, to);
await ProxTagger.tagRemove(data, from, to)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment