Skip to content

Commit 0e2a8f6

Browse files
committed
Add nodered cleanup code
1 parent 77c66e5 commit 0e2a8f6

3 files changed

Lines changed: 123 additions & 78 deletions

File tree

OpenFlow/src/Messages/Message.ts

Lines changed: 119 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -747,26 +747,17 @@ export class Message {
747747
this.Send(cli);
748748
}
749749

750-
private async GetInstanceName(cli: WebSocketClient, _id: string): Promise<string> {
750+
private async GetInstanceName(_id: string, myid: string, myusername: string, jwt: string): Promise<string> {
751751
var name: string = "";
752-
if (_id !== null && _id !== undefined && _id !== "" && _id != cli.user._id) {
753-
var res = await Config.db.query<User>({ _id: _id }, null, 1, 0, null, "users", cli.jwt);
752+
if (_id !== null && _id !== undefined && _id !== "" && _id != myid) {
753+
var res = await Config.db.query<User>({ _id: _id }, null, 1, 0, null, "users", jwt);
754754
if (res.length == 0) {
755755
throw new Error("Unknown userid " + _id);
756756
}
757757
name = res[0].username;
758-
// if (name !== null && name !== undefined && name !== "" && name != username) {
759-
// }
760-
// var exists = await User.FindByUsername(name, cli.jwt);
761758
} else {
762-
name = cli.user.username;
763-
}
764-
// if (name !== null && name !== undefined && name !== "" && name != username) {
765-
// var exists = await User.FindByUsername(name, cli.jwt);
766-
// if (exists == null) {
767-
// throw new Error("Unknown name " + name);
768-
// }
769-
// }
759+
name = myusername;
760+
}
770761
name = name.split("@").join("").split(".").join("");
771762
name = name.toLowerCase();
772763
return name;
@@ -796,7 +787,7 @@ export class Message {
796787
var user: NoderedUser;
797788
cli._logger.debug("[" + cli.user.username + "] EnsureNoderedInstance");
798789
if (_id === null || _id === undefined || _id === "") _id = cli.user._id;
799-
var name = await this.GetInstanceName(cli, _id);
790+
var name = await this.GetInstanceName(_id, cli.user._id, cli.user.username, cli.jwt);
800791

801792
var users = await Config.db.query<NoderedUser>({ _id: _id }, null, 1, 0, null, "users", cli.jwt);
802793
if (users.length == 0) {
@@ -827,6 +818,7 @@ export class Message {
827818
await noderedadmins.Save(cli.jwt);
828819

829820
var resources = new V1ResourceRequirements();
821+
var hasbilling: boolean = false;
830822
if (user.nodered && user.nodered.resources) {
831823
if (Util.IsNullEmpty(Config.stripe_api_secret)) {
832824
if (user.nodered.resources.limits) {
@@ -845,6 +837,9 @@ export class Message {
845837
var billing: Billing = billings[0];
846838
resources.limits = {};
847839
resources.limits.memory = billing.memory;
840+
if (!Util.IsNullEmpty(billing.openflowuserplan)) {
841+
hasbilling = true;
842+
}
848843
}
849844

850845
}
@@ -856,11 +851,11 @@ export class Message {
856851
if (skipcreate) return;
857852
cli._logger.debug("[" + cli.user.username + "] Deployment " + name + " not found in " + namespace + " so creating it");
858853
var _deployment = {
859-
metadata: { name: name, namespace: namespace, app: name },
854+
metadata: { name: name, namespace: namespace, app: name, labels: { billed: hasbilling.toString(), userid: _id } },
860855
spec: {
861856
replicas: 1,
862857
template: {
863-
metadata: { labels: { name: name, app: name } },
858+
metadata: { labels: { name: name, app: name, billed: hasbilling.toString(), userid: _id } },
864859
spec: {
865860
containers: [
866861
{
@@ -908,17 +903,22 @@ export class Message {
908903
// await KubeUtil.instance().ExtensionsV1beta1Api.createNamespacedDeployment(namespace, (_deployment as any));
909904
await KubeUtil.instance().ExtensionsV1beta1Api.createNamespacedDeployment(namespace, (_deployment as any));
910905
} else {
911-
console.log(deployment.spec.template.spec.containers[0].resources);
912-
if (deployment.spec.template.spec.containers[0].resources && resources) {
913-
deployment.spec.template.spec.containers[0].resources = resources;
914-
}
906+
deployment.spec.template.spec.containers[0].resources = resources;
915907
var f = deployment.spec.template.spec.containers[0].env.filter(x => x.name == "api_allow_anonymous");
916908
if (f.length > 0) {
917909
f[0].value = user.nodered.api_allow_anonymous.toString();
918910
}
919-
920-
921-
await KubeUtil.instance().ExtensionsV1beta1Api.replaceNamespacedDeployment(name, namespace, (deployment as any));
911+
deployment.metadata.labels.billed = hasbilling.toString();
912+
deployment.spec.template.metadata.labels.billed = hasbilling.toString();
913+
deployment.metadata.labels.userid = _id;
914+
deployment.spec.template.metadata.labels.userid = _id;
915+
try {
916+
await KubeUtil.instance().ExtensionsV1beta1Api.replaceNamespacedDeployment(name, namespace, (deployment as any));
917+
} catch (error) {
918+
cli._logger.error("[" + cli.user.username + "] failed updating noeredinstance");
919+
cli._logger.error("[" + cli.user.username + "] " + JSON.stringify(error));
920+
throw new Error("failed updating noeredinstance");
921+
}
922922
}
923923

924924
cli._logger.debug("[" + cli.user.username + "] GetService");
@@ -972,61 +972,51 @@ export class Message {
972972
throw new Error("failed locating useringress");
973973
}
974974
}
975+
private async _DeleteNoderedInstance(_id: string, myuserid: string, myusername: string, jwt: string): Promise<void> {
976+
var name = await this.GetInstanceName(_id, myuserid, myusername, jwt);
977+
var namespace = Config.namespace;
978+
var hostname = Config.nodered_domain_schema.replace("$nodered_id$", name);
979+
980+
var deployment = await KubeUtil.instance().GetDeployment(namespace, name);
981+
if (deployment != null) {
982+
await KubeUtil.instance().ExtensionsV1beta1Api.deleteNamespacedDeployment(name, namespace);
983+
}
984+
var service = await KubeUtil.instance().GetService(namespace, name);
985+
if (service != null) {
986+
await KubeUtil.instance().CoreV1Api.deleteNamespacedService(name, namespace);
987+
}
988+
var replicaset = await KubeUtil.instance().GetReplicaset(namespace, "app", name);
989+
if (replicaset !== null) {
990+
KubeUtil.instance().AppsV1Api.deleteNamespacedReplicaSet(replicaset.metadata.name, namespace);
991+
}
992+
var ingress = await KubeUtil.instance().GetIngress(namespace, "useringress");
993+
if (ingress !== null) {
994+
var updated = false;
995+
for (var i = ingress.spec.rules.length - 1; i >= 0; i--) {
996+
if (ingress.spec.rules[i].host == hostname) {
997+
ingress.spec.rules.splice(i, 1);
998+
updated = true;
999+
}
1000+
}
1001+
if (updated) {
1002+
delete ingress.metadata.creationTimestamp;
1003+
await KubeUtil.instance().ExtensionsV1beta1Api.replaceNamespacedIngress("useringress", namespace, ingress);
1004+
}
1005+
} else {
1006+
throw new Error("failed locating useringress");
1007+
}
1008+
}
9751009
private async DeleteNoderedInstance(cli: WebSocketClient): Promise<void> {
9761010
this.Reply();
9771011
var msg: DeleteNoderedInstanceMessage;
9781012
var user: User;
9791013
try {
980-
cli._logger.debug("[" + cli.user.username + "] DeleteNoderedInstance");
9811014
msg = DeleteNoderedInstanceMessage.assign(this.data);
982-
var name = await this.GetInstanceName(cli, msg._id);
983-
var namespace = Config.namespace;
984-
var hostname = Config.nodered_domain_schema.replace("$nodered_id$", name);
1015+
cli._logger.debug("[" + cli.user.username + "] DeleteNoderedInstance");
1016+
await this._DeleteNoderedInstance(msg._id, cli.user._id, cli.user.username, cli.jwt);
9851017

986-
// for now, lets not delete role
987-
// var role: Role = await Role.FindByNameOrId(name + "noderedadmins", null);
988-
// if (role !== null) {
989-
// var jwt: string = TokenUser.rootToken();
990-
// await Config.db.DeleteOne(role._id, "users", jwt);
991-
// }
992-
var deployment = await KubeUtil.instance().GetDeployment(namespace, name);
993-
if (deployment != null) {
994-
await KubeUtil.instance().ExtensionsV1beta1Api.deleteNamespacedDeployment(name, namespace);
995-
}
996-
var service = await KubeUtil.instance().GetService(namespace, name);
997-
if (service != null) {
998-
await KubeUtil.instance().CoreV1Api.deleteNamespacedService(name, namespace);
999-
}
1000-
var replicaset = await KubeUtil.instance().GetReplicaset(namespace, "app", name);
1001-
if (replicaset !== null) {
1002-
KubeUtil.instance().AppsV1Api.deleteNamespacedReplicaSet(replicaset.metadata.name, namespace);
1003-
}
1004-
// var list = await KubeUtil.instance().CoreV1Api.listNamespacedPod(namespace);
1005-
// for (var i = 0; i < list.body.items.length; i++) {
1006-
// var item = list.body.items[i];
1007-
// // if (item.metadata.labels.app === name || item.metadata.labels.name === name) {
1008-
// if (item.metadata.labels.app === name) {
1009-
// await KubeUtil.instance().CoreV1Api.deleteNamespacedPod(item.metadata.name, namespace);
1010-
// }
1011-
// }
1012-
var ingress = await KubeUtil.instance().GetIngress(namespace, "useringress");
1013-
if (ingress !== null) {
1014-
var updated = false;
1015-
for (var i = ingress.spec.rules.length - 1; i >= 0; i--) {
1016-
if (ingress.spec.rules[i].host == hostname) {
1017-
ingress.spec.rules.splice(i, 1);
1018-
updated = true;
1019-
}
1020-
}
1021-
if (updated) {
1022-
delete ingress.metadata.creationTimestamp;
1023-
await KubeUtil.instance().ExtensionsV1beta1Api.replaceNamespacedIngress("useringress", namespace, ingress);
1024-
}
1025-
} else {
1026-
cli._logger.error("[" + cli.user.username + "] failed locating useringress");
1027-
if (msg !== null && msg !== undefined) msg.error = "failed locating useringress";
1028-
}
10291018
} catch (error) {
1019+
cli._logger.error("[" + cli.user.username + "] failed locating useringress");
10301020
this.data = "";
10311021
cli._logger.error(error);
10321022
//msg.error = JSON.stringify(error, null, 2);
@@ -1079,7 +1069,7 @@ export class Message {
10791069
try {
10801070
cli._logger.debug("[" + cli.user.username + "] RestartNoderedInstance");
10811071
msg = RestartNoderedInstanceMessage.assign(this.data);
1082-
var name = await this.GetInstanceName(cli, msg._id);
1072+
var name = await this.GetInstanceName(msg._id, cli.user._id, cli.user.username, cli.jwt);
10831073
var namespace = Config.namespace;
10841074
// var hostname = Config.nodered_domain_schema.replace("$nodered_id$", name);
10851075

@@ -1111,7 +1101,7 @@ export class Message {
11111101
try {
11121102
cli._logger.debug("[" + cli.user.username + "] GetNoderedInstance");
11131103
msg = GetNoderedInstanceMessage.assign(this.data);
1114-
var name = await this.GetInstanceName(cli, msg._id);
1104+
var name = await this.GetInstanceName(msg._id, cli.user._id, cli.user.username, cli.jwt);
11151105
var namespace = Config.namespace;
11161106
// var hostname = Config.nodered_domain_schema.replace("$nodered_id$", name);
11171107

@@ -1120,9 +1110,31 @@ export class Message {
11201110
var found: any = null;
11211111
msg.result = null;
11221112
msg.results = [];
1113+
var rootjwt = TokenUser.rootToken();
11231114
if (list.body.items.length > 0) {
11241115
for (var i = 0; i < list.body.items.length; i++) {
1125-
var item = list.body.items[i];
1116+
if (!Util.IsNullEmpty(Config.stripe_api_secret)) {
1117+
var item = list.body.items[i];
1118+
var create = item.metadata.creationTimestamp;
1119+
var billed = item.metadata.labels.billed;
1120+
var image = item.spec.containers[0].image
1121+
var userid = item.metadata.labels.userid;
1122+
if (image.indexOf("openflownodered") > 0 && !Util.IsNullEmpty(userid)) {
1123+
try {
1124+
var date = new Date();
1125+
var a: number = (date as any) - (create as any);
1126+
// var diffminutes = a / (1000 * 60);
1127+
var diffhours = a / (1000 * 60 * 60);
1128+
if (billed != "true" && diffhours > 24) {
1129+
cli._logger.debug("[" + cli.user.username + "] Remove un billed nodered instance " + item.metadata.name + " that has been running for " + diffhours + " hours");
1130+
await this._DeleteNoderedInstance(userid, cli.user._id, cli.user.username, rootjwt);
1131+
}
1132+
// console.log(item.metadata.name + " " + diffminutes + " min / " + diffhours + " hours");
1133+
} catch (error) {
1134+
}
1135+
}
1136+
}
1137+
11261138
if (!Util.IsNullEmpty(msg.name) && item.metadata.name == msg.name && cli.user.HasRoleName("admins")) {
11271139
found = item;
11281140
msg.results.push(item);
@@ -1159,7 +1171,7 @@ export class Message {
11591171
try {
11601172
cli._logger.debug("[" + cli.user.username + "] GetNoderedInstance");
11611173
msg = GetNoderedInstanceLogMessage.assign(this.data);
1162-
var name = await this.GetInstanceName(cli, msg._id);
1174+
var name = await this.GetInstanceName(msg._id, cli.user._id, cli.user.username, cli.jwt);
11631175
var namespace = Config.namespace;
11641176

11651177
var list = await KubeUtil.instance().CoreV1Api.listNamespacedPod(namespace);
@@ -1819,8 +1831,12 @@ export class Message {
18191831
if (customer != null && billing != null && customer.subscriptions != null && customer.subscriptions.total_count > 0) {
18201832
for (var i = 0; i < customer.subscriptions.data.length; i++) {
18211833
var sub = customer.subscriptions.data[i];
1822-
if (sub.plan != null && sub.plan.metadata != null && sub.plan.metadata.memory != null) {
1823-
newmemory = sub.plan.metadata.memory;
1834+
for (var y = 0; y < sub.items.data.length; y++) {
1835+
var subitem = sub.items.data[y];
1836+
if (subitem.plan != null && subitem.plan.metadata != null && subitem.plan.metadata.memory != null) {
1837+
newmemory = subitem.plan.metadata.memory;
1838+
}
1839+
18241840
}
18251841
}
18261842
}
@@ -1858,6 +1874,32 @@ export class Message {
18581874
billing = await Config.db._UpdateOne(null, billing, "users", 3, true, rootjwt);
18591875
}
18601876
}
1877+
if (customer != null && billing != null) {
1878+
var openflowuserplan: string = "";
1879+
var supportplan: string = "";
1880+
var supporthourplan: string = "";
1881+
1882+
customer.subscriptions.data.filter(s => {
1883+
s.items.data.filter(y => {
1884+
if (y.plan.metadata.supporthourplan == "true") {
1885+
supporthourplan = y.id;
1886+
}
1887+
if (y.plan.metadata.supportplan == "true") {
1888+
supportplan = y.id;
1889+
}
1890+
if (y.plan.metadata.openflowuser == "true") {
1891+
openflowuserplan = y.id;
1892+
}
1893+
});
1894+
return false;
1895+
});
1896+
if (billing.openflowuserplan != openflowuserplan || billing.supportplan != supportplan || billing.supporthourplan != supporthourplan) {
1897+
billing.openflowuserplan = openflowuserplan;
1898+
billing.supportplan = supportplan;
1899+
billing.supporthourplan = supporthourplan;
1900+
billing = await Config.db._UpdateOne(null, billing, "users", 3, true, rootjwt);
1901+
}
1902+
}
18611903
msg.customer = customer;
18621904

18631905
} catch (error) {

OpenFlow/src/Messages/StripeMessage.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ export class Billing extends Base {
1313
public hascard: boolean;
1414
public coupon: string;
1515
public memory: string;
16+
public openflowuserplan: string;
17+
public supportplan: string;
18+
public supporthourplan: string;
1619
constructor() {
1720
super();
1821
this._type = "billing";

OpenFlow/src/public/Nodered.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ <h1 translate lib="web">sockets</h1>
8484
</div>
8585
</section>
8686
<section>
87-
<div class="form-group" ng-show="menuctrl.hasrole('admins')">
87+
<div class="form-group" ng-show="menuctrl.hasrole('admins') && menuctrl.WebSocketClient.stripe_api_key == ''">
8888
<label class="col-sm-3 control-label"><span translate lib="web">memory</span>: </label>
8989
<div class="col-sm-9">
9090
<select class="form-control" ng-model="ctrl.limitsmemory">

0 commit comments

Comments
 (0)