smol updates

pull/1/head
plazmoid 2 years ago
parent 0a077af936
commit a594348a30
  1. 2
      Makefile.toml
  2. 1
      bin/u_agent/src/lib.rs
  3. 5
      bin/u_panel/Cargo.toml
  4. 2
      bin/u_panel/src/server/fe/package.json
  5. 6
      bin/u_panel/src/server/fe/src/app/app.module.ts
  6. 26
      bin/u_panel/src/server/fe/src/app/core/tables/agent.component.ts
  7. 12
      bin/u_panel/src/server/fe/src/app/core/tables/dialogs/agent-info-dialog.html
  8. 11
      bin/u_panel/src/server/fe/src/app/core/tables/dialogs/agent_info.component.ts
  9. 1
      bin/u_panel/src/server/fe/src/app/core/tables/dialogs/index.ts
  10. 12
      bin/u_panel/src/server/fe/src/app/core/tables/job.component.ts
  11. 15
      bin/u_panel/src/server/fe/src/app/core/tables/result.component.ts
  12. 3
      bin/u_panel/src/server/fe/src/app/core/tables/table.component.html
  13. 5
      bin/u_panel/src/server/fe/src/app/core/tables/table.component.less
  14. 6
      bin/u_panel/src/server/fe/src/app/core/tables/table.component.ts
  15. 3
      bin/u_panel/src/server/fe/src/app/core/utils.ts
  16. 6
      bin/u_server/src/db.rs
  17. 3
      images/integration-tests/u_db.Dockerfile
  18. 5
      integration/docker_compose.py
  19. 20
      integration/integration_tests.py
  20. 4
      lib/u_lib/src/api.rs
  21. 7
      todos.txt

@ -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 ${@}
'''

@ -1,7 +1,6 @@
// TODO:
// поддержка питона
// резолв адреса управляющего сервера через DoT
// кроссплатформенность (реализовать интерфейс для винды и никсов)
#[macro_use]
extern crate log;

@ -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"

@ -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",

@ -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
],

@ -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<AgentModel> {
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
});
}
}

@ -0,0 +1,12 @@
<mat-dialog-content>
<div>
<p>Alias: {{data.alias}}</p>
<p>Username: {{data.username}}</p>
<p>Hostname: {{data.hostname}}</p>
<p>Platform: {{data.platform}}</p>
</div>
</mat-dialog-content>
<mat-dialog-actions align="end">
<button mat-button cdkFocusInitial>Edit</button>
<button mat-button mat-dialog-close>Cancel</button>
</mat-dialog-actions>

@ -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) { }
}

@ -0,0 +1 @@
export * from './agent_info.component';

@ -14,22 +14,22 @@ export class JobComponent extends TablesComponent<JobModel> {
{
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<JobModel> {
{
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) { }
}

@ -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<ResultModel> {
{
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<ResultModel> {
{
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) {
}
}

@ -23,7 +23,8 @@
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<tr mat-row class="data-table-row" *matRowDef="let row; columns: displayedColumns;"
(click)="show_item_dialog(row)"></tr>
<tr class="mat-row" *matNoDataRow>
<td class="mat-cell">No data</td>

@ -22,3 +22,8 @@
#refresh_btn {
margin-left: 10px;
}
.data-table-row:hover {
background: whitesmoke;
cursor: pointer;
}

@ -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<T> implements OnInit {
@ -13,7 +14,7 @@ export abstract class TablesComponent<T> 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<T> 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<T> implements OnInit {
this.table_data.filter = filterValue.trim().toLowerCase();
}
abstract show_item_dialog(obj: T): void;
abstract columns: ColumnDef<T>[];
abstract displayedColumns: string[];

@ -0,0 +1,3 @@
export function epochToStr(epoch: number): string {
return new Date(epoch * 1000).toLocaleString('en-GB')
}

@ -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<Arc<Mutex<UDB>>> = OnceCell::new();
static DB: OnceCell<Mutex<UDB>> = 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()

@ -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

@ -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)

@ -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()
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()

@ -46,9 +46,9 @@ impl ClientHandler {
}
}
async fn _req<P: AsMsg + Debug, M: AsMsg + DeserializeOwned + Debug + Default>(
async fn _req<P: AsMsg, M: AsMsg + DeserializeOwned + Default>(
&self,
url: impl AsRef<str> + Debug,
url: impl AsRef<str>,
payload: P,
) -> Result<M> {
let request = self

@ -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
Loading…
Cancel
Save