mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
Docker: Adaptive sudo
This commit is contained in:
@@ -2,7 +2,6 @@ import 'dart:async';
|
|||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:dartssh2/dartssh2.dart';
|
import 'package:dartssh2/dartssh2.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
import 'package:toolbox/core/extension/stringx.dart';
|
import 'package:toolbox/core/extension/stringx.dart';
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ class ContainerdClient {
|
|||||||
final String version;
|
final String version;
|
||||||
final String goVersion;
|
final String goVersion;
|
||||||
final String gitCommit;
|
final String gitCommit;
|
||||||
final String builtTime;
|
final String? builtTime;
|
||||||
final int built;
|
final int? built; // more fields should be marked nullable
|
||||||
final String osArch;
|
final String? osArch;
|
||||||
final String os;
|
final String os;
|
||||||
|
|
||||||
ContainerdClient({
|
ContainerdClient({
|
||||||
@@ -49,22 +49,22 @@ class ContainerdClient {
|
|||||||
|
|
||||||
factory ContainerdClient.fromJson(Map<String, dynamic> json) =>
|
factory ContainerdClient.fromJson(Map<String, dynamic> json) =>
|
||||||
ContainerdClient(
|
ContainerdClient(
|
||||||
apiVersion: json["ApiVersion"], // should be ApiVersion?
|
apiVersion: json["ApiVersion"],
|
||||||
version: json["Version"],
|
version: json["Version"],
|
||||||
goVersion: json["GoVersion"],
|
goVersion: json["GoVersion"],
|
||||||
gitCommit: json["GitCommit"],
|
gitCommit: json["GitCommit"],
|
||||||
builtTime: json["BuiltTime"],
|
builtTime: json["BuildTime"],
|
||||||
built: json["Built"],
|
built: json["Built"], // should be Build?
|
||||||
osArch: json["OsArch"],
|
osArch: json["OsArch"],
|
||||||
os: json["Os"],
|
os: json["Os"],
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
"APIVersion": apiVersion,
|
"ApiVersion": apiVersion,
|
||||||
"Version": version,
|
"Version": version,
|
||||||
"GoVersion": goVersion,
|
"GoVersion": goVersion,
|
||||||
"GitCommit": gitCommit,
|
"GitCommit": gitCommit,
|
||||||
"BuiltTime": builtTime,
|
"BuildTime": builtTime,
|
||||||
"Built": built,
|
"Built": built,
|
||||||
"OsArch": osArch,
|
"OsArch": osArch,
|
||||||
"Os": os,
|
"Os": os,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import 'package:toolbox/data/model/container/type.dart';
|
|||||||
import 'package:toolbox/data/model/container/version.dart';
|
import 'package:toolbox/data/model/container/version.dart';
|
||||||
import 'package:toolbox/data/res/logger.dart';
|
import 'package:toolbox/data/res/logger.dart';
|
||||||
import 'package:toolbox/data/res/store.dart';
|
import 'package:toolbox/data/res/store.dart';
|
||||||
|
import 'package:toolbox/core/extension/uint8list.dart';
|
||||||
|
|
||||||
final _dockerNotFound =
|
final _dockerNotFound =
|
||||||
RegExp(r"command not found|Unknown command|Command '\w+' not found");
|
RegExp(r"command not found|Unknown command|Command '\w+' not found");
|
||||||
@@ -47,25 +48,36 @@ class ContainerProvider extends ChangeNotifier {
|
|||||||
Future<bool> _checkDockerInstalled(SSHClient client) async {
|
Future<bool> _checkDockerInstalled(SSHClient client) async {
|
||||||
final session = await client.execute("docker");
|
final session = await client.execute("docker");
|
||||||
await session.done;
|
await session.done;
|
||||||
// print('docker code: ${session.exitCode}');
|
// debugPrint('docker code: ${session.exitCode}');
|
||||||
return session.exitCode == 0;
|
return session.exitCode == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
String _removeSudoPrompts(String value) {
|
String _removeSudoPrompts(String value) {
|
||||||
final regex = RegExp(r"\[sudo\] password for \w+:");
|
final regex = RegExp(r"\[sudo\] password for \w+:");
|
||||||
if (value.startsWith(regex)){
|
if (value.startsWith(regex)) {
|
||||||
return value.replaceFirstMapped(regex, (match) => "");
|
return value.replaceFirstMapped(regex, (match) => "");
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> _requiresSudo() async {
|
||||||
|
final psResult = await client?.run(_wrap(ContainerCmdType.ps.exec(type)));
|
||||||
|
if (psResult == null) return true;
|
||||||
|
if (psResult.string.toLowerCase().contains("permission denied")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> refresh() async {
|
Future<void> refresh() async {
|
||||||
var raw = '';
|
var raw = '';
|
||||||
var rawErr = '';
|
var rawErr = '';
|
||||||
print('exec: ${_wrap(ContainerCmdType.execAll(type))}');
|
debugPrint('exec: ${_wrap(ContainerCmdType.execAll(type))}');
|
||||||
|
|
||||||
|
final sudo = await _requiresSudo();
|
||||||
|
|
||||||
await client?.execWithPwd(
|
await client?.execWithPwd(
|
||||||
_wrap(ContainerCmdType.execAll(type)),
|
_wrap(ContainerCmdType.execAll(type, sudo: sudo)),
|
||||||
context: context,
|
context: context,
|
||||||
onStdout: (data, _) => raw = '$raw$data',
|
onStdout: (data, _) => raw = '$raw$data',
|
||||||
onStderr: (data, _) => raw = '$rawErr$data',
|
onStderr: (data, _) => raw = '$rawErr$data',
|
||||||
@@ -74,10 +86,10 @@ class ContainerProvider extends ChangeNotifier {
|
|||||||
raw = _removeSudoPrompts(raw);
|
raw = _removeSudoPrompts(raw);
|
||||||
rawErr = _removeSudoPrompts(rawErr);
|
rawErr = _removeSudoPrompts(rawErr);
|
||||||
|
|
||||||
print('result raw [$raw, $rawErr]');
|
debugPrint('result raw [$raw, $rawErr]');
|
||||||
|
|
||||||
final dockerInstalled = await _checkDockerInstalled(client!);
|
final dockerInstalled = await _checkDockerInstalled(client!);
|
||||||
// print("docker installed = $dockerInstalled");
|
// debugPrint("docker installed = $dockerInstalled");
|
||||||
|
|
||||||
if (!dockerInstalled ||
|
if (!dockerInstalled ||
|
||||||
raw.contains(_dockerNotFound) ||
|
raw.contains(_dockerNotFound) ||
|
||||||
@@ -101,7 +113,7 @@ class ContainerProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
// Parse docker version
|
// Parse docker version
|
||||||
final verRaw = ContainerCmdType.version.find(segments);
|
final verRaw = ContainerCmdType.version.find(segments);
|
||||||
print('version raw = $verRaw\n');
|
debugPrint('version raw = $verRaw\n');
|
||||||
try {
|
try {
|
||||||
final containerVersion = Containerd.fromRawJson(verRaw);
|
final containerVersion = Containerd.fromRawJson(verRaw);
|
||||||
version = containerVersion.client.version;
|
version = containerVersion.client.version;
|
||||||
@@ -228,8 +240,8 @@ enum ContainerCmdType {
|
|||||||
images,
|
images,
|
||||||
;
|
;
|
||||||
|
|
||||||
String exec(ContainerType type) {
|
String exec(ContainerType type, {bool sudo = false}) {
|
||||||
final prefix = type.name;
|
final prefix = sudo ? 'sudo -S ${type.name}' : type.name;
|
||||||
return switch (this) {
|
return switch (this) {
|
||||||
ContainerCmdType.version => '$prefix version $_jsonFmt',
|
ContainerCmdType.version => '$prefix version $_jsonFmt',
|
||||||
ContainerCmdType.ps => '$prefix ps -a $_jsonFmt',
|
ContainerCmdType.ps => '$prefix ps -a $_jsonFmt',
|
||||||
@@ -238,6 +250,7 @@ enum ContainerCmdType {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static String execAll(ContainerType type) =>
|
static String execAll(ContainerType type, {bool sudo = false}) => values
|
||||||
values.map((e) => e.exec(type)).join(' && echo $seperator && ');
|
.map((e) => e.exec(type, sudo: sudo))
|
||||||
|
.join(' && echo $seperator && ');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:typed_data';
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:computer/computer.dart';
|
import 'package:computer/computer.dart';
|
||||||
|
|||||||
Reference in New Issue
Block a user