diff --git a/bin/u_panel/src/server/fe/src/app/app.module.ts b/bin/u_panel/src/server/fe/src/app/app.module.ts index a78705c..037df53 100644 --- a/bin/u_panel/src/server/fe/src/app/app.module.ts +++ b/bin/u_panel/src/server/fe/src/app/app.module.ts @@ -11,6 +11,8 @@ import { MatInputModule } from '@angular/material/input'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { HttpClientModule } from '@angular/common/http'; import { MatDialogModule } from '@angular/material/dialog'; +import { MatIconModule } from '@angular/material/icon'; +import { FormsModule } from '@angular/forms'; import { AgentComponent, JobComponent, ResultComponent } from './core/tables'; import { AgentInfoDialogComponent } from './core/tables/dialogs'; @@ -33,6 +35,8 @@ import { AgentInfoDialogComponent } from './core/tables/dialogs'; MatInputModule, MatDialogModule, MatProgressSpinnerModule, + MatIconModule, + FormsModule, BrowserAnimationsModule ], providers: [], diff --git a/bin/u_panel/src/server/fe/src/app/core/models/agent.model.ts b/bin/u_panel/src/server/fe/src/app/core/models/agent.model.ts index 8015ee2..cd8ef76 100644 --- a/bin/u_panel/src/server/fe/src/app/core/models/agent.model.ts +++ b/bin/u_panel/src/server/fe/src/app/core/models/agent.model.ts @@ -3,6 +3,7 @@ import { UTCDate } from "."; export interface AgentModel { alias: string | null, hostname: string, + host_info: string, id: string, is_root: boolean, is_root_allowed: boolean, diff --git a/bin/u_panel/src/server/fe/src/app/core/services/api.service.ts b/bin/u_panel/src/server/fe/src/app/core/services/api.service.ts index a7a609b..26d5810 100644 --- a/bin/u_panel/src/server/fe/src/app/core/services/api.service.ts +++ b/bin/u_panel/src/server/fe/src/app/core/services/api.service.ts @@ -21,12 +21,12 @@ export class ApiTableService { return await firstValueFrom(this.http.post>(this.requestUrl, cmd)) } - async getOne(id: string): Promise> { - const resp = await this.req(`${this.area} read ${id}`) + async getOne(id: string, area: string = this.area): Promise> { + const resp = await this.req(`${area} read ${id}`) if (resp.data.length === 0) { return { status: 'err', - data: `${id} not found in ${this.area}` + data: `${id} not found in ${area}` } } return { diff --git a/bin/u_panel/src/server/fe/src/app/core/tables/agent.component.html b/bin/u_panel/src/server/fe/src/app/core/tables/agent.component.html index 80318c1..1bfd13a 100644 --- a/bin/u_panel/src/server/fe/src/app/core/tables/agent.component.html +++ b/bin/u_panel/src/server/fe/src/app/core/tables/agent.component.html @@ -8,7 +8,7 @@ Filter - + @@ -51,7 +51,12 @@ diff --git a/bin/u_panel/src/server/fe/src/app/core/tables/agent.component.ts b/bin/u_panel/src/server/fe/src/app/core/tables/agent.component.ts index c7ae033..dae0ad0 100644 --- a/bin/u_panel/src/server/fe/src/app/core/tables/agent.component.ts +++ b/bin/u_panel/src/server/fe/src/app/core/tables/agent.component.ts @@ -44,10 +44,16 @@ export class AgentComponent extends TablesComponent implements OnDes this.data_source!.getOne(id).then(resp => { if (resp.status === 'ok') { const dialog = this.info_dlg.open(AgentInfoDialogComponent, { - data: resp.data as AgentModel + data: resp.data as AgentModel, + width: '500px', }); + const saveSub = dialog.componentInstance.onSave.subscribe(result => { + this.data_source!.update(result).then(_ => this.loadTableData()).catch(emitErr) + }) + dialog.afterClosed().subscribe(result => { + saveSub.unsubscribe() this.router.navigate(['.'], { relativeTo: this.route }) }) } else { @@ -56,6 +62,12 @@ export class AgentComponent extends TablesComponent implements OnDes }).catch(emitErr) } + deleteItem(id: string) { + if (confirm(`Delete ${id}?`)) { + this.data_source!.delete(id).catch(emitErr) + } + } + ngOnDestroy(): void { this.dialogSubscr.unsubscribe() } diff --git a/bin/u_panel/src/server/fe/src/app/core/tables/dialogs/agent-info-dialog.html b/bin/u_panel/src/server/fe/src/app/core/tables/dialogs/agent-info-dialog.html index 2afdeab..260b345 100644 --- a/bin/u_panel/src/server/fe/src/app/core/tables/dialogs/agent-info-dialog.html +++ b/bin/u_panel/src/server/fe/src/app/core/tables/dialogs/agent-info-dialog.html @@ -1,15 +1,64 @@ +

Agent info

+

Editing agent info

-
-

ID: {{data.id}}

-

Alias: {{data.alias}}

-

Username: {{data.username}}

-

Hostname: {{data.hostname}}

-

Platform: {{data.platform}}

-

Registration time: {{data.regtime.secs_since_epoch * 1000 | date:'long'}}

-

Last active time: {{data.last_active.secs_since_epoch * 1000 | date:'long'}}

-
+

+ + ID + + +

+

+ + Alias + + +

+

+ + Username + + +

+

+ + Hostname + + +

+

+ + Host info + + +

+

+ + Platform + + +

+

+ + Is root + + +

+

+ + Registration time + + +

+

+ + Last active time + + +

- + + \ No newline at end of file diff --git a/bin/u_panel/src/server/fe/src/app/core/tables/dialogs/agent_info.component.ts b/bin/u_panel/src/server/fe/src/app/core/tables/dialogs/agent_info.component.ts index 1d85364..9195e61 100644 --- a/bin/u_panel/src/server/fe/src/app/core/tables/dialogs/agent_info.component.ts +++ b/bin/u_panel/src/server/fe/src/app/core/tables/dialogs/agent_info.component.ts @@ -1,11 +1,23 @@ import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA } from '@angular/material/dialog'; import { AgentModel } from '../../models/agent.model'; +import { EventEmitter } from '@angular/core'; +import { Input } from '@angular/core'; @Component({ selector: 'agent-info-dialog', templateUrl: 'agent-info-dialog.html', + styleUrls: ['info-dialog.component.less'] }) export class AgentInfoDialogComponent { + is_preview = true; + onSave = new EventEmitter(); + + constructor(@Inject(MAT_DIALOG_DATA) public data: AgentModel) { } -} \ No newline at end of file + + updateAgent() { + console.log(this.data); + this.onSave.emit(this.data); + } +} \ No newline at end of file diff --git a/bin/u_panel/src/server/fe/src/app/core/tables/dialogs/info-dialog.component.less b/bin/u_panel/src/server/fe/src/app/core/tables/dialogs/info-dialog.component.less new file mode 100644 index 0000000..bc8e5fb --- /dev/null +++ b/bin/u_panel/src/server/fe/src/app/core/tables/dialogs/info-dialog.component.less @@ -0,0 +1,3 @@ +.info-dlg-field { + width: 100%; +} \ No newline at end of file diff --git a/bin/u_panel/src/server/fe/src/app/core/tables/job.component.html b/bin/u_panel/src/server/fe/src/app/core/tables/job.component.html index 1234aa6..f99fbfd 100644 --- a/bin/u_panel/src/server/fe/src/app/core/tables/job.component.html +++ b/bin/u_panel/src/server/fe/src/app/core/tables/job.component.html @@ -8,7 +8,7 @@ Filter - +
- + +
diff --git a/bin/u_panel/src/server/fe/src/app/core/tables/result.component.html b/bin/u_panel/src/server/fe/src/app/core/tables/result.component.html index e9abbd7..d8bf8d9 100644 --- a/bin/u_panel/src/server/fe/src/app/core/tables/result.component.html +++ b/bin/u_panel/src/server/fe/src/app/core/tables/result.component.html @@ -8,7 +8,7 @@ Filter - +
diff --git a/bin/u_panel/src/server/fe/src/app/core/tables/table.component.less b/bin/u_panel/src/server/fe/src/app/core/tables/table.component.less index 6b3ee6b..167dd69 100644 --- a/bin/u_panel/src/server/fe/src/app/core/tables/table.component.less +++ b/bin/u_panel/src/server/fe/src/app/core/tables/table.component.less @@ -23,6 +23,10 @@ margin-left: 10px; } +.data-table-row { + height: 30px; +} + .data-table-row:hover { background: whitesmoke; } \ No newline at end of file diff --git a/bin/u_panel/src/server/fe/src/app/core/tables/table.component.ts b/bin/u_panel/src/server/fe/src/app/core/tables/table.component.ts index f0cb6da..062fb90 100644 --- a/bin/u_panel/src/server/fe/src/app/core/tables/table.component.ts +++ b/bin/u_panel/src/server/fe/src/app/core/tables/table.component.ts @@ -20,10 +20,10 @@ export abstract class TablesComponent implements OnInit { ngOnInit() { this.data_source = new ApiTableService(this._httpClient, this.area); - this.fetchMany(); + this.loadTableData(); } - async fetchMany() { + async loadTableData() { this.isLoadingResults = true; //possibly needs try/catch const data = await this.data_source!.getMany(); diff --git a/bin/u_server/src/handlers.rs b/bin/u_server/src/handlers.rs index 39f3398..eb890e4 100644 --- a/bin/u_server/src/handlers.rs +++ b/bin/u_server/src/handlers.rs @@ -103,7 +103,7 @@ impl Endpoints { Reportable::Assigned(mut result) => { let result_agent_id = &result.agent_id; if id != *result_agent_id { - warn!("Ids are not equal! actual id: {id}, job id: {result_agent_id}"); + warn!("Ids are not equal! actual id: {id}, id from job: {result_agent_id}"); continue; } result.state = JobState::Finished; diff --git a/integration/docker.py b/integration/docker.py index 355e517..36035a3 100644 --- a/integration/docker.py +++ b/integration/docker.py @@ -90,7 +90,7 @@ class Compose: ] def __init__(self): - self.container_tpl = 'integration_%s_%d' + self.container_tpl = 'integration-%s-%d' self.cmd_container = self.container_tpl % ('tests_runner', 1) self.ALL_CONTAINERS = [self.container_tpl % (c, 1) for c in self.ALL_IMAGES] diff --git a/lib/u_lib/src/models/agent.rs b/lib/u_lib/src/models/agent.rs index 5ad5549..61caf8d 100644 --- a/lib/u_lib/src/models/agent.rs +++ b/lib/u_lib/src/models/agent.rs @@ -41,6 +41,7 @@ pub enum AgentState { pub struct Agent { pub alias: Option, pub hostname: String, + pub host_info: String, pub id: Uuid, pub ip_gray: Option, pub ip_white: Option, @@ -86,7 +87,8 @@ impl Agent { #[cfg(unix)] pub async fn gather() -> Self { let mut builder = NamedJobRunner::from_shell(vec![ - ("hostname", "hostname"), + ("hostname", "hostnamectl hostname"), + ("host_info", "hostnamectl --json=pretty"), ("is_root", "id -u"), ("username", "id -un"), ]) @@ -98,6 +100,7 @@ impl Agent { Self { hostname: decoder(builder.pop("hostname")), + host_info: decoder(builder.pop("host_info")), is_root: &decoder(builder.pop("is_root")) == "0", username: decoder(builder.pop("username")), platform: Platform::current_as_string(), @@ -105,11 +108,6 @@ impl Agent { } } - #[cfg(not(unix))] - pub async fn gather() -> Self { - todo!() - } - pub async fn run() -> Agent { Agent::gather().await } @@ -121,6 +119,7 @@ impl Default for Agent { alias: None, id: get_self_uid(), hostname: String::new(), + host_info: String::new(), is_root: false, is_root_allowed: false, last_active: SystemTime::now(), diff --git a/lib/u_lib/src/models/schema.rs b/lib/u_lib/src/models/schema.rs index fd2db7b..1b47bc7 100644 --- a/lib/u_lib/src/models/schema.rs +++ b/lib/u_lib/src/models/schema.rs @@ -4,6 +4,7 @@ table! { agents (id) { alias -> Nullable, hostname -> Text, + host_info -> Text, id -> Uuid, ip_gray -> Nullable, ip_white -> Nullable, diff --git a/lib/u_lib/src/runner.rs b/lib/u_lib/src/runner.rs index 6383cea..9d5576b 100644 --- a/lib/u_lib/src/runner.rs +++ b/lib/u_lib/src/runner.rs @@ -52,7 +52,9 @@ impl JobRunner { .into_iter() .map(|jm| { let job_id = jm.id; - JobCache::insert(jm); + if !JobCache::contains(job_id) { + JobCache::insert(jm); + } AssignedJobById { job_id, ..Default::default() @@ -166,8 +168,9 @@ impl NamedJobRunner { let job_metas: Vec = named_jobs .into_vec() .into_iter() - .map(|(alias, meta)| { + .map(|(alias, mut meta)| { job_names.push(alias); + meta.alias = Some(alias.to_string()); meta }) .collect(); diff --git a/migrations/2020-10-24-111622_create_all/up.sql b/migrations/2020-10-24-111622_create_all/up.sql index 4edc097..c99082f 100644 --- a/migrations/2020-10-24-111622_create_all/up.sql +++ b/migrations/2020-10-24-111622_create_all/up.sql @@ -6,6 +6,7 @@ CREATE TYPE AgentState AS ENUM ('new', 'active', 'banned'); CREATE TABLE IF NOT EXISTS agents ( alias TEXT, hostname TEXT NOT NULL, + host_info TEXT NOT NULL, id UUID NOT NULL DEFAULT uuid_generate_v4(), ip_gray TEXT, ip_white TEXT,