From a594348a303c5d190404ea05adb6a9801748f296 Mon Sep 17 00:00:00 2001 From: plazmoid Date: Mon, 12 Sep 2022 02:28:20 +0500 Subject: [PATCH] smol updates --- Makefile.toml | 2 +- bin/u_agent/src/lib.rs | 1 - bin/u_panel/Cargo.toml | 5 ---- bin/u_panel/src/server/fe/package.json | 2 +- .../src/server/fe/src/app/app.module.ts | 6 ++++- .../fe/src/app/core/tables/agent.component.ts | 26 +++++++++++++++---- .../tables/dialogs/agent-info-dialog.html | 12 +++++++++ .../tables/dialogs/agent_info.component.ts | 11 ++++++++ .../fe/src/app/core/tables/dialogs/index.ts | 1 + .../fe/src/app/core/tables/job.component.ts | 12 +++++---- .../src/app/core/tables/result.component.ts | 15 +++++++---- .../src/app/core/tables/table.component.html | 3 ++- .../src/app/core/tables/table.component.less | 5 ++++ .../fe/src/app/core/tables/table.component.ts | 6 +++-- .../src/server/fe/src/app/core/utils.ts | 3 +++ bin/u_server/src/db.rs | 6 ++--- images/integration-tests/u_db.Dockerfile | 5 ++-- integration/docker_compose.py | 5 ++-- integration/integration_tests.py | 22 +++++++++++++--- lib/u_lib/src/api.rs | 4 +-- todos.txt | 7 +++++ 21 files changed, 119 insertions(+), 40 deletions(-) create mode 100644 bin/u_panel/src/server/fe/src/app/core/tables/dialogs/agent-info-dialog.html create mode 100644 bin/u_panel/src/server/fe/src/app/core/tables/dialogs/agent_info.component.ts create mode 100644 bin/u_panel/src/server/fe/src/app/core/tables/dialogs/index.ts create mode 100644 bin/u_panel/src/server/fe/src/app/core/utils.ts create mode 100644 todos.txt diff --git a/Makefile.toml b/Makefile.toml index c5fb8e0..63e14e2 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -71,7 +71,7 @@ args = ["test", "--target", "${TARGET}", "--lib", "--", "${@}"] [tasks.integration] script = ''' -echo "!!! This task doesn't perform project rebuild, trigger it manually if need" +[[ ! -d "./target/${TARGET}/${PROFILE_OVERRIDE}" ]] && echo 'No target folder. Build project first' && exit 1 cd ./integration bash integration_tests.sh ${@} ''' diff --git a/bin/u_agent/src/lib.rs b/bin/u_agent/src/lib.rs index 09e016f..597df48 100644 --- a/bin/u_agent/src/lib.rs +++ b/bin/u_agent/src/lib.rs @@ -1,7 +1,6 @@ // TODO: // поддержка питона // резолв адреса управляющего сервера через DoT -// кроссплатформенность (реализовать интерфейс для винды и никсов) #[macro_use] extern crate log; diff --git a/bin/u_panel/Cargo.toml b/bin/u_panel/Cargo.toml index 1ea2be9..1e69c0c 100644 --- a/bin/u_panel/Cargo.toml +++ b/bin/u_panel/Cargo.toml @@ -8,20 +8,15 @@ edition = "2021" [dependencies] actix-web = "4.1" -backtrace = "0.3.61" structopt = "0.3.21" uuid = "0.6.5" serde_json = "1.0.4" serde = { version = "1.0.114", features = ["derive"] } tokio = { version = "1.11.0", features = ["rt", "rt-multi-thread"] } u_lib = { version = "*", path = "../../lib/u_lib", features = ["panel"] } -tui = { version = "0.16", default-features = false, features = ['crossterm'] } -crossterm = "0.22.1" anyhow = "1.0.44" strum = { version = "0.22.0", features = ["derive"] } once_cell = "1.8.0" -crossbeam = "0.8.1" -async-channel = "1.6.1" tracing = "0.1.29" tracing-subscriber = { version = "0.3.3", features = ["env-filter"]} signal-hook = "0.3.12" diff --git a/bin/u_panel/src/server/fe/package.json b/bin/u_panel/src/server/fe/package.json index 9cc9000..fb86167 100644 --- a/bin/u_panel/src/server/fe/package.json +++ b/bin/u_panel/src/server/fe/package.json @@ -27,7 +27,7 @@ "zone.js": "~0.11.4" }, "devDependencies": { - "@angular-devkit/build-angular": "~13.1.2", + "@angular-devkit/build-angular": "^13.3.9", "@angular/cli": "~13.1.2", "@angular/compiler-cli": "~13.1.0", "@types/jasmine": "~3.10.0", 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 b251fa0..a78705c 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 @@ -10,14 +10,17 @@ import { MatButtonModule } from '@angular/material/button' 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 { AgentComponent, JobComponent, ResultComponent } from './core/tables'; +import { AgentInfoDialogComponent } from './core/tables/dialogs'; @NgModule({ declarations: [ AppComponent, AgentComponent, JobComponent, - ResultComponent + ResultComponent, + AgentInfoDialogComponent ], imports: [ BrowserModule, @@ -28,6 +31,7 @@ import { AgentComponent, JobComponent, ResultComponent } from './core/tables'; MatButtonModule, MatFormFieldModule, MatInputModule, + MatDialogModule, MatProgressSpinnerModule, BrowserAnimationsModule ], 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 8b1b5cb..dea2e61 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 @@ -1,6 +1,10 @@ import { Component, OnInit } from '@angular/core'; import { TablesComponent } from './table.component'; import { AgentModel } from '../models'; +import { AgentInfoDialogComponent } from './dialogs/agent_info.component'; +import { HttpClient } from '@angular/common/http'; +import { MatDialog } from '@angular/material/dialog'; +import { epochToStr } from '../utils'; @Component({ selector: 'agent-table', @@ -8,34 +12,46 @@ import { AgentModel } from '../models'; styleUrls: ['./table.component.less'] }) export class AgentComponent extends TablesComponent { + + constructor(public override _httpClient: HttpClient, public override info_dlg: MatDialog) { + super(_httpClient, info_dlg); + } + area = 'agents' as const; columns = [ { def: "id", name: "ID", - cell: (cell: AgentModel) => `${cell.id}` + cell: (cell: AgentModel) => cell.id }, { def: "alias", name: "Alias", - cell: (cell: AgentModel) => `${cell.alias}` + cell: (cell: AgentModel) => cell.alias ?? "" }, { def: "username", name: "User", - cell: (cell: AgentModel) => `${cell.username}` + cell: (cell: AgentModel) => cell.username }, { def: "hostname", name: "Host", - cell: (cell: AgentModel) => `${cell.hostname}` + cell: (cell: AgentModel) => cell.hostname }, { def: "last_active", name: "Last active", - cell: (cell: AgentModel) => `${cell.last_active.secs_since_epoch}` + cell: (cell: AgentModel) => epochToStr(cell.last_active.secs_since_epoch) }, ] + displayedColumns = this.columns.map((c) => c.def); + + show_item_dialog(obj: AgentModel) { + const dialog = this.info_dlg.open(AgentInfoDialogComponent, { + data: obj + }); + } } 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 new file mode 100644 index 0000000..eaf5e5a --- /dev/null +++ b/bin/u_panel/src/server/fe/src/app/core/tables/dialogs/agent-info-dialog.html @@ -0,0 +1,12 @@ + +
+

Alias: {{data.alias}}

+

Username: {{data.username}}

+

Hostname: {{data.hostname}}

+

Platform: {{data.platform}}

+
+
+ + + + \ 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 new file mode 100644 index 0000000..1c318ca --- /dev/null +++ b/bin/u_panel/src/server/fe/src/app/core/tables/dialogs/agent_info.component.ts @@ -0,0 +1,11 @@ +import { Component, Inject } from '@angular/core'; +import { MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { AgentModel } from '../../models/agent.model'; + +@Component({ + selector: 'agent-info-dialog', + templateUrl: 'agent-info-dialog.html', +}) +export class AgentInfoDialogComponent { + constructor(@Inject(MAT_DIALOG_DATA) public data: AgentModel) { } +} \ No newline at end of file diff --git a/bin/u_panel/src/server/fe/src/app/core/tables/dialogs/index.ts b/bin/u_panel/src/server/fe/src/app/core/tables/dialogs/index.ts new file mode 100644 index 0000000..1aa08ec --- /dev/null +++ b/bin/u_panel/src/server/fe/src/app/core/tables/dialogs/index.ts @@ -0,0 +1 @@ +export * from './agent_info.component'; \ No newline at end of file diff --git a/bin/u_panel/src/server/fe/src/app/core/tables/job.component.ts b/bin/u_panel/src/server/fe/src/app/core/tables/job.component.ts index 27d8d42..28f9c92 100644 --- a/bin/u_panel/src/server/fe/src/app/core/tables/job.component.ts +++ b/bin/u_panel/src/server/fe/src/app/core/tables/job.component.ts @@ -14,22 +14,22 @@ export class JobComponent extends TablesComponent { { def: "id", name: "ID", - cell: (cell: JobModel) => `${cell.id}` + cell: (cell: JobModel) => cell.id }, { def: "alias", name: "Alias", - cell: (cell: JobModel) => `${cell.alias}` + cell: (cell: JobModel) => cell.alias }, { def: "argv", name: "Cmd-line args", - cell: (cell: JobModel) => `${cell.argv}` + cell: (cell: JobModel) => cell.argv }, { def: "platform", name: "Platform", - cell: (cell: JobModel) => `${cell.platform}` + cell: (cell: JobModel) => cell.platform }, { def: "payload", @@ -39,8 +39,10 @@ export class JobComponent extends TablesComponent { { def: "etype", name: "Type", - cell: (cell: JobModel) => `${cell.exec_type}` + cell: (cell: JobModel) => cell.exec_type }, ] displayedColumns = this.columns.map((c) => c.def); + + show_item_dialog(obj: JobModel) { } } diff --git a/bin/u_panel/src/server/fe/src/app/core/tables/result.component.ts b/bin/u_panel/src/server/fe/src/app/core/tables/result.component.ts index 964c8cd..3b7cade 100644 --- a/bin/u_panel/src/server/fe/src/app/core/tables/result.component.ts +++ b/bin/u_panel/src/server/fe/src/app/core/tables/result.component.ts @@ -1,6 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { TablesComponent } from './table.component'; import { ResultModel } from '../models'; +import { epochToStr } from '../utils'; @Component({ selector: 'result-table', @@ -14,22 +15,22 @@ export class ResultComponent extends TablesComponent { { def: "id", name: "ID", - cell: (cell: ResultModel) => `${cell.id}` + cell: (cell: ResultModel) => cell.id }, { def: "alias", name: "Alias", - cell: (cell: ResultModel) => `${cell.alias}` + cell: (cell: ResultModel) => cell.alias }, { def: "agent_id", name: "Agent ID", - cell: (cell: ResultModel) => `${cell.agent_id}` + cell: (cell: ResultModel) => cell.agent_id }, { def: "job_id", name: "Job ID", - cell: (cell: ResultModel) => `${cell.job_id}` + cell: (cell: ResultModel) => cell.job_id }, { def: "state", @@ -39,8 +40,12 @@ export class ResultComponent extends TablesComponent { { def: "last_updated", name: "Last updated", - cell: (cell: ResultModel) => `${cell.updated.secs_since_epoch}` + cell: (cell: ResultModel) => epochToStr(cell.updated.secs_since_epoch) }, ] displayedColumns = this.columns.map((c) => c.def); + + show_item_dialog(obj: ResultModel) { + + } } diff --git a/bin/u_panel/src/server/fe/src/app/core/tables/table.component.html b/bin/u_panel/src/server/fe/src/app/core/tables/table.component.html index 777d508..c54abd9 100644 --- a/bin/u_panel/src/server/fe/src/app/core/tables/table.component.html +++ b/bin/u_panel/src/server/fe/src/app/core/tables/table.component.html @@ -23,7 +23,8 @@ - + No data 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 6a4475a..931742f 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 @@ -21,4 +21,9 @@ #refresh_btn { margin-left: 10px; +} + +.data-table-row:hover { + background: whitesmoke; + cursor: pointer; } \ 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 5581de6..39107d7 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 @@ -4,6 +4,7 @@ import { catchError, map, startWith, switchMap } from 'rxjs/operators'; import { HttpClient } from '@angular/common/http'; import { ApiTableService } from '../'; import { MatTableDataSource } from '@angular/material/table'; +import { MatDialog } from '@angular/material/dialog'; @Directive() export abstract class TablesComponent implements OnInit { @@ -13,7 +14,7 @@ export abstract class TablesComponent implements OnInit { isLoadingResults = true; - constructor(private _httpClient: HttpClient) { + constructor(public _httpClient: HttpClient, public info_dlg: MatDialog) { this.table_data = new MatTableDataSource; } @@ -37,7 +38,7 @@ export abstract class TablesComponent implements OnInit { this.isLoadingResults = false; if (data === null) { - return []; + return "no data returned" } // Only refresh the result length if there is new data. In case of rate @@ -54,6 +55,7 @@ export abstract class TablesComponent implements OnInit { this.table_data.filter = filterValue.trim().toLowerCase(); } + abstract show_item_dialog(obj: T): void; abstract columns: ColumnDef[]; abstract displayedColumns: string[]; diff --git a/bin/u_panel/src/server/fe/src/app/core/utils.ts b/bin/u_panel/src/server/fe/src/app/core/utils.ts new file mode 100644 index 0000000..27aadd8 --- /dev/null +++ b/bin/u_panel/src/server/fe/src/app/core/utils.ts @@ -0,0 +1,3 @@ +export function epochToStr(epoch: number): string { + return new Date(epoch * 1000).toLocaleString('en-GB') +} \ No newline at end of file diff --git a/bin/u_server/src/db.rs b/bin/u_server/src/db.rs index d0929ca..8eb3a55 100644 --- a/bin/u_server/src/db.rs +++ b/bin/u_server/src/db.rs @@ -2,7 +2,7 @@ use crate::errors::{Error, SResult}; use diesel::{pg::PgConnection, prelude::*, result::Error as DslError}; use once_cell::sync::OnceCell; use serde::Deserialize; -use std::sync::{Arc, Mutex, MutexGuard}; +use std::sync::{Mutex, MutexGuard}; use u_lib::{ models::{schema, Agent, AssignedJob, JobMeta, JobState}, utils::load_env, @@ -13,7 +13,7 @@ pub struct UDB { pub conn: PgConnection, } -static DB: OnceCell>> = OnceCell::new(); +static DB: OnceCell> = OnceCell::new(); #[derive(Deserialize)] struct DBEnv { @@ -34,7 +34,7 @@ impl UDB { let instance = UDB { conn: PgConnection::establish(&db_url).unwrap(), }; - Arc::new(Mutex::new(instance)) + Mutex::new(instance) }) .lock() .unwrap() diff --git a/images/integration-tests/u_db.Dockerfile b/images/integration-tests/u_db.Dockerfile index 783d887..8578b44 100644 --- a/images/integration-tests/u_db.Dockerfile +++ b/images/integration-tests/u_db.Dockerfile @@ -1,5 +1,6 @@ -FROM postgres:13.3 +FROM postgres:14.5 +ENV DEBIAN_FRONTEND=noninteractive RUN apt update && apt upgrade -y RUN apt install -y curl build-essential libpq-dev iproute2 RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable --profile minimal @@ -8,4 +9,4 @@ RUN rustup target add x86_64-unknown-linux-musl RUN cargo install diesel_cli --no-default-features --features postgres RUN mkdir -p /unki -COPY u_db_entrypoint.sh /unki/ \ No newline at end of file +COPY u_db_entrypoint.sh /unki/ diff --git a/integration/docker_compose.py b/integration/docker_compose.py index 69ef302..0c445dd 100644 --- a/integration/docker_compose.py +++ b/integration/docker_compose.py @@ -15,7 +15,8 @@ class Compose: def __init__(self): 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_CONTAINERS] + self.ALL_CONTAINERS = [self.container_tpl % + (c, 1) for c in self.ALL_CONTAINERS] self.scaled_svc = {} self.scale("u_agent", 2) @@ -28,7 +29,7 @@ class Compose: def _call(self, *args): cmd = [ 'docker-compose', - '--no-ansi', + '--ansi=never', ] + list(args) log(f'Running docker-compose command: {cmd}') subprocess.check_call(cmd) diff --git a/integration/integration_tests.py b/integration/integration_tests.py index e4fe460..3402c9a 100644 --- a/integration/integration_tests.py +++ b/integration/integration_tests.py @@ -14,21 +14,35 @@ def abort_handler(s, _): cluster.down() +def usage_exit(): + usage = f"""Usage: + python {__file__.split('/')[-1]} [--rebuild] [--preserve] [--no-run]""" + + print(usage) + sys.exit(1) + + def run_tests(): - force_rebuild = '--rebuild' in sys.argv - preserve_containers = '--preserve' in sys.argv + allowed_args = set(["--rebuild", "--preserve", "--no-run"]) + args = sys.argv[1:] + if not set(args).issubset(allowed_args): + usage_exit() + force_rebuild = '--rebuild' in args + preserve_containers = '--preserve' in args + only_setup_cluster = '--no-run' in args for s in (signal.SIGTERM, signal.SIGINT, signal.SIGHUP): signal.signal(s, abort_handler) rebuild_images_if_needed(force_rebuild) try: cluster.up() cluster.is_alive() - cluster.run('cargo test --test integration') + if not only_setup_cluster: + cluster.run('cargo test --test integration') except Exception as e: err(e) sys.exit(1) finally: - if not preserve_containers: + if not preserve_containers and not only_setup_cluster: cluster.down() diff --git a/lib/u_lib/src/api.rs b/lib/u_lib/src/api.rs index 7669da2..a860365 100644 --- a/lib/u_lib/src/api.rs +++ b/lib/u_lib/src/api.rs @@ -46,9 +46,9 @@ impl ClientHandler { } } - async fn _req( + async fn _req( &self, - url: impl AsRef + Debug, + url: impl AsRef, payload: P, ) -> Result { let request = self diff --git a/todos.txt b/todos.txt new file mode 100644 index 0000000..5be7b2a --- /dev/null +++ b/todos.txt @@ -0,0 +1,7 @@ +Upload/download files +More tests +Agent update (use more JobType's) +Erase log macros in release mode +Bump wine version to test agent on windows +Store downloaded payload on disk instead of memory +Improve web interface \ No newline at end of file