Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
RoboPLC
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
黄新宇
RoboPLC
Commits
10e4c1e4
提交
10e4c1e4
authored
7月 30, 2024
作者:
Serhij S
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
docker support
上级
8834d453
隐藏空白字符变更
内嵌
并排
正在显示
7 个修改的文件
包含
152 行增加
和
26 行删除
+152
-26
Cargo.lock
roboplc-cli/Cargo.lock
+2
-1
Cargo.toml
roboplc-cli/Cargo.toml
+2
-1
arguments.rs
roboplc-cli/src/arguments.rs
+34
-2
common.rs
roboplc-cli/src/common.rs
+22
-0
flashing.rs
roboplc-cli/src/flashing.rs
+63
-18
main.rs
roboplc-cli/src/main.rs
+14
-2
project.rs
roboplc-cli/src/project.rs
+15
-2
没有找到文件。
roboplc-cli/Cargo.lock
浏览文件 @
10e4c1e4
...
@@ -695,13 +695,14 @@ dependencies = [
...
@@ -695,13 +695,14 @@ dependencies = [
[[package]]
[[package]]
name = "roboplc-cli"
name = "roboplc-cli"
version = "0.4.
1
"
version = "0.4.
2
"
dependencies = [
dependencies = [
"ansi_term",
"ansi_term",
"clap",
"clap",
"colored",
"colored",
"dirs",
"dirs",
"futures-util",
"futures-util",
"once_cell",
"serde",
"serde",
"serde_json",
"serde_json",
"shlex",
"shlex",
...
...
roboplc-cli/Cargo.toml
浏览文件 @
10e4c1e4
[package]
[package]
name
=
"roboplc-cli"
name
=
"roboplc-cli"
version
=
"0.4.
1
"
version
=
"0.4.
2
"
edition
=
"2021"
edition
=
"2021"
authors
=
[
"Serhij S. <div@altertech.com>"
]
authors
=
[
"Serhij S. <div@altertech.com>"
]
license
=
"Apache-2.0"
license
=
"Apache-2.0"
...
@@ -28,6 +28,7 @@ which = "3"
...
@@ -28,6 +28,7 @@ which = "3"
term_size
=
"0.3.2"
term_size
=
"0.3.2"
tokio
=
{
version
=
"=1.36"
,
features
=
[
"rt"
,
"fs"
]
}
tokio
=
{
version
=
"=1.36"
,
features
=
[
"rt"
,
"fs"
]
}
tokio-tungstenite
=
{
version
=
"0.23.1"
,
features
=
["rustls"]
}
tokio-tungstenite
=
{
version
=
"0.23.1"
,
features
=
["rustls"]
}
once_cell
=
"1.19.0"
[target.'cfg(windows)'.dependencies]
[target.'cfg(windows)'.dependencies]
ansi_term
=
"0.12.1"
ansi_term
=
"0.12.1"
...
...
roboplc-cli/src/arguments.rs
浏览文件 @
10e4c1e4
...
@@ -63,6 +63,34 @@ pub struct NewCommand {
...
@@ -63,6 +63,34 @@ pub struct NewCommand {
pub
extras
:
Vec
<
String
>
,
pub
extras
:
Vec
<
String
>
,
#[clap(short
=
'L'
,
long,
help
=
"Locking policy)"
,
default_value
=
"rt-safe"
)]
#[clap(short
=
'L'
,
long,
help
=
"Locking policy)"
,
default_value
=
"rt-safe"
)]
pub
locking
:
LockingPolicy
,
pub
locking
:
LockingPolicy
,
#[clap(long,
help
=
"Docker project (specify an architecture)"
)]
pub
docker
:
Option
<
Docker
>
,
}
#[derive(ValueEnum,
Copy,
Clone)]
pub
enum
Docker
{
#[clap(name
=
"x86_64"
,
help
=
"x86_64 architecture"
)]
X86_64
,
#[clap(name
=
"aarch64"
,
help
=
"ARM-64 bit architecture"
)]
Aarch64
,
}
impl
Docker
{
pub
fn
target
(
self
)
->
&
'static
str
{
match
self
{
Docker
::
X86_64
=>
"x86_64-unknown-linux-gnu"
,
Docker
::
Aarch64
=>
"aarch64-unknown-linux-gnu"
,
}
}
pub
fn
binary_path_for
(
self
,
name
:
&
str
)
->
PathBuf
{
PathBuf
::
from_iter
(
vec!
[
"target"
,
self
.target
(),
"release"
,
name
])
}
pub
fn
docker_image_name
(
self
)
->
&
'static
str
{
match
self
{
Docker
::
X86_64
=>
"bmauto/roboplc-x86_64:latest"
,
Docker
::
Aarch64
=>
"bmauto/roboplc-aarch64:latest"
,
}
}
}
}
#[derive(ValueEnum,
Copy,
Clone)]
#[derive(ValueEnum,
Copy,
Clone)]
...
@@ -98,10 +126,14 @@ pub struct FlashCommand {
...
@@ -98,10 +126,14 @@ pub struct FlashCommand {
#[clap(
#[clap(
short
=
'f'
,
short
=
'f'
,
long,
long,
help
=
"Force flash (automatically put remote in CONFIG mode)"
help
=
"Force flash (automatically put remote in CONFIG mode)
, for Docker: run privileged
"
)]
)]
pub
force
:
bool
,
pub
force
:
bool
,
#[clap(short
=
'r'
,
long,
help
=
"Put remote in RUN mode after flashing"
)]
#[clap(
short
=
'r'
,
long,
help
=
"Put remote in RUN mode after flashing, for Docker: run the container"
)]
pub
run
:
bool
,
pub
run
:
bool
,
}
}
...
...
roboplc-cli/src/common.rs
浏览文件 @
10e4c1e4
...
@@ -68,15 +68,37 @@ impl fmt::Display for Mode {
...
@@ -68,15 +68,37 @@ impl fmt::Display for Mode {
}
}
}
}
#[derive(Deserialize,
Debug)]
struct
CargoToml
{
package
:
CargoPackage
,
}
#[derive(Deserialize,
Debug)]
struct
CargoPackage
{
name
:
String
,
version
:
String
,
}
pub
fn
find_robo_toml
()
->
Option
<
PathBuf
>
{
pub
fn
find_robo_toml
()
->
Option
<
PathBuf
>
{
let
mut
current_dir
=
env
::
current_dir
()
.ok
()
?
;
let
mut
current_dir
=
env
::
current_dir
()
.ok
()
?
;
loop
{
loop
{
let
mut
cargo_toml_path
=
current_dir
.clone
();
let
mut
cargo_toml_path
=
current_dir
.clone
();
cargo_toml_path
.push
(
"Cargo.toml"
);
cargo_toml_path
.push
(
"Cargo.toml"
);
if
cargo_toml_path
.exists
()
{
if
cargo_toml_path
.exists
()
{
let
contents
=
std
::
fs
::
read_to_string
(
cargo_toml_path
)
.expect
(
"Failed to read Cargo.toml"
);
let
cargo_toml
:
CargoToml
=
toml
::
from_str
(
&
contents
)
.expect
(
"Failed to parse Cargo.toml"
);
crate
::
TARGET_PACKAGE_NAME
.set
(
cargo_toml
.package.name
)
.expect
(
"Failed to set target package name"
);
crate
::
TARGET_PACKAGE_VERSION
.set
(
cargo_toml
.package.version
)
.expect
(
"Failed to set target package version"
);
let
mut
roboplc_toml_path
=
current_dir
.clone
();
let
mut
roboplc_toml_path
=
current_dir
.clone
();
roboplc_toml_path
.push
(
CONFIG_FILE_NAME
);
roboplc_toml_path
.push
(
CONFIG_FILE_NAME
);
if
roboplc_toml_path
.exists
()
{
if
roboplc_toml_path
.exists
()
{
std
::
env
::
set_current_dir
(
current_dir
)
.expect
(
"Failed to set current dir"
);
return
Some
(
roboplc_toml_path
);
return
Some
(
roboplc_toml_path
);
}
}
}
}
...
...
roboplc-cli/src/flashing.rs
浏览文件 @
10e4c1e4
...
@@ -34,25 +34,70 @@ fn flash_file(
...
@@ -34,25 +34,70 @@ fn flash_file(
if
exec_only
{
if
exec_only
{
return
crate
::
exec
::
exec
(
url
,
key
,
file
,
force
,
program_args
);
return
crate
::
exec
::
exec
(
url
,
key
,
file
,
force
,
program_args
);
}
}
let
(
content_type
,
data
)
=
MultipartBuilder
::
new
()
if
let
Some
(
docker_img
)
=
url
.strip_prefix
(
"docker://"
)
{
.add_file
(
"file"
,
file
)
?
let
tag
=
std
::
env
::
var
(
"ROBO_DOCKER_TAG"
)
.unwrap_or_else
(|
_
|
{
.add_text
(
crate
::
TARGET_PACKAGE_VERSION
"params"
,
.get
()
&
serde_json
::
to_string
(
&
json!
{
.cloned
()
{
.unwrap_or_else
(||
"latest"
.to_owned
())
"force"
:
force
,
});
"run"
:
run
,
let
img_name
=
format!
(
"{}:{}"
,
docker_img
,
tag
);
}
println!
(
"Building docker image: {}"
,
img_name
.yellow
());
let
result
=
std
::
process
::
Command
::
new
(
"docker"
)
.args
([
"build"
,
"-t"
,
&
img_name
,
"."
])
.status
()
?
;
if
!
result
.success
()
{
return
Err
(
"Compilation failed"
.into
());
}
println!
();
println!
(
"Docker image ready: {}"
,
img_name
.green
());
if
run
{
println!
(
"Running docker image..."
);
let
mut
args
=
vec!
[
"run"
,
"--rm"
,
"-it"
];
let
port
=
std
::
env
::
var
(
"ROBO_DOCKER_PORT"
)
.unwrap_or_else
(|
_
|
"7700"
.to_owned
());
let
port_mapping
=
if
port
.is_empty
()
{
None
}
else
{
Some
(
format!
(
"{}:7700"
,
port
))
};
if
let
Some
(
ref
port_mapping
)
=
port_mapping
{
args
.push
(
"-p"
);
args
.push
(
port_mapping
);
println!
(
"RoboPLC manager is available at {}"
,
format!
(
"http://localhost:{}"
,
port
)
.yellow
()
);
}
if
force
{
args
.push
(
"--privileged"
);
}
args
.push
(
&
img_name
);
let
result
=
std
::
process
::
Command
::
new
(
"docker"
)
.args
(
args
)
.status
()
?
;
if
!
result
.success
()
{
return
Err
(
"Execution failed"
.into
());
}
}
}
else
{
let
(
content_type
,
data
)
=
MultipartBuilder
::
new
()
.add_file
(
"file"
,
file
)
?
.add_text
(
"params"
,
&
serde_json
::
to_string
(
&
json!
{
{
"force"
:
force
,
"run"
:
run
,
}
})
?
,
})
?
,
)
?
)
?
.finish
()
?
;
.finish
()
?
;
agent
agent
.post
(
&
format!
(
"{}{}/flash"
,
url
,
API_PREFIX
))
.post
(
&
format!
(
"{}{}/flash"
,
url
,
API_PREFIX
))
.set
(
"x-auth-key"
,
key
)
.set
(
"x-auth-key"
,
key
)
.set
(
"content-type"
,
&
content_type
)
.set
(
"content-type"
,
&
content_type
)
.send_bytes
(
&
data
)
.send_bytes
(
&
data
)
.process_error
()
?
;
.process_error
()
?
;
}
Ok
(())
Ok
(())
}
}
...
...
roboplc-cli/src/main.rs
浏览文件 @
10e4c1e4
...
@@ -3,6 +3,7 @@ use std::{fs, time::Duration};
...
@@ -3,6 +3,7 @@ use std::{fs, time::Duration};
use
arguments
::{
Args
,
SubCommand
};
use
arguments
::{
Args
,
SubCommand
};
use
clap
::
Parser
;
use
clap
::
Parser
;
use
common
::{
find_robo_toml
,
Mode
};
use
common
::{
find_robo_toml
,
Mode
};
use
once_cell
::
sync
::
OnceCell
;
use
ureq
::
Agent
;
use
ureq
::
Agent
;
use
crate
::
config
::
Config
;
use
crate
::
config
::
Config
;
...
@@ -11,6 +12,10 @@ const API_PREFIX: &str = "/roboplc/api";
...
@@ -11,6 +12,10 @@ const API_PREFIX: &str = "/roboplc/api";
const
DEFAULT_TIMEOUT
:
u64
=
60
;
const
DEFAULT_TIMEOUT
:
u64
=
60
;
const
TPL_DEFAULT_RS
:
&
str
=
include_str!
(
"../tpl/default.rs"
);
const
TPL_DEFAULT_RS
:
&
str
=
include_str!
(
"../tpl/default.rs"
);
// filled by find_robo_toml if Cargo.toml is found
static
TARGET_PACKAGE_NAME
:
OnceCell
<
String
>
=
OnceCell
::
new
();
static
TARGET_PACKAGE_VERSION
:
OnceCell
<
String
>
=
OnceCell
::
new
();
mod
arguments
;
mod
arguments
;
mod
common
;
mod
common
;
mod
config
;
mod
config
;
...
@@ -20,6 +25,7 @@ mod project;
...
@@ -20,6 +25,7 @@ mod project;
mod
remote
;
mod
remote
;
mod
ureq_err
;
mod
ureq_err
;
#[allow(clippy
::
too_many_lines)]
fn
main
()
->
Result
<
(),
Box
<
dyn
std
::
error
::
Error
>>
{
fn
main
()
->
Result
<
(),
Box
<
dyn
std
::
error
::
Error
>>
{
#[cfg(target_os
=
"windows"
)]
#[cfg(target_os
=
"windows"
)]
let
_ansi_enabled
=
ansi_term
::
enable_ansi_support
();
let
_ansi_enabled
=
ansi_term
::
enable_ansi_support
();
...
@@ -61,7 +67,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
...
@@ -61,7 +67,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
}
}
maybe_url
=
maybe_url
.map
(|
v
|
{
maybe_url
=
maybe_url
.map
(|
v
|
{
let
mut
u
=
v
.trim_end_matches
(
'/'
)
.to_owned
();
let
mut
u
=
v
.trim_end_matches
(
'/'
)
.to_owned
();
if
!
u
.starts_with
(
"http://"
)
&&
!
u
.starts_with
(
"https://"
)
{
if
!
u
.starts_with
(
"http://"
)
&&
!
u
.starts_with
(
"https://"
)
&&
!
u
.starts_with
(
"docker://"
)
{
u
=
format!
(
"http://{}"
,
u
);
u
=
format!
(
"http://{}"
,
u
);
}
}
u
u
...
@@ -71,7 +77,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
...
@@ -71,7 +77,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
return
Ok
(());
return
Ok
(());
}
}
let
url
=
maybe_url
.ok_or
(
"URL not specified"
)
?
;
let
url
=
maybe_url
.ok_or
(
"URL not specified"
)
?
;
let
key
=
maybe_key
.ok_or
(
"Key not specified"
)
?
;
let
key
=
if
let
Some
(
k
)
=
maybe_key
{
k
}
else
if
url
.starts_with
(
"docker://"
)
{
String
::
new
()
}
else
{
return
Err
(
"Key not specified"
.into
());
};
let
timeout
=
maybe_timeout
.unwrap_or
(
DEFAULT_TIMEOUT
);
let
timeout
=
maybe_timeout
.unwrap_or
(
DEFAULT_TIMEOUT
);
let
agent
:
Agent
=
ureq
::
AgentBuilder
::
new
()
let
agent
:
Agent
=
ureq
::
AgentBuilder
::
new
()
.timeout_read
(
Duration
::
from_secs
(
timeout
))
.timeout_read
(
Duration
::
from_secs
(
timeout
))
...
...
roboplc-cli/src/project.rs
浏览文件 @
10e4c1e4
use
std
::
env
;
use
std
::
{
env
,
fs
::
File
,
io
::
Write
}
;
use
colored
::
Colorize
as
_
;
use
colored
::
Colorize
as
_
;
...
@@ -42,7 +42,7 @@ pub fn create(
...
@@ -42,7 +42,7 @@ pub fn create(
true
,
true
,
)
?
;
)
?
;
add_dependency
(
"tracing@0.1"
,
&
[
"log"
],
None
,
false
)
?
;
add_dependency
(
"tracing@0.1"
,
&
[
"log"
],
None
,
false
)
?
;
let
robo_toml
=
Config
{
let
mut
robo_toml
=
Config
{
remote
:
config
::
Remote
{
remote
:
config
::
Remote
{
key
:
maybe_key
,
key
:
maybe_key
,
url
:
maybe_url
,
url
:
maybe_url
,
...
@@ -51,6 +51,19 @@ pub fn create(
...
@@ -51,6 +51,19 @@ pub fn create(
build
:
<
_
>
::
default
(),
build
:
<
_
>
::
default
(),
build_custom
:
<
_
>
::
default
(),
build_custom
:
<
_
>
::
default
(),
};
};
if
let
Some
(
docker_arch
)
=
opts
.docker
{
robo_toml
.build.target
=
Some
(
docker_arch
.target
()
.to_owned
());
if
robo_toml
.remote.url
.is_none
()
{
robo_toml
.remote.url
=
Some
(
format!
(
"docker://{}"
,
opts
.name
));
}
let
mut
f
=
File
::
create
(
"Dockerfile"
)
?
;
writeln!
(
f
,
"FROM {}"
,
docker_arch
.docker_image_name
())
?
;
writeln!
(
f
,
"COPY ./{} /var/roboplc/program/current"
,
docker_arch
.binary_path_for
(
&
opts
.name
)
.display
()
)
?
;
}
std
::
fs
::
write
(
CONFIG_FILE_NAME
,
toml
::
to_string_pretty
(
&
robo_toml
)
?
)
?
;
std
::
fs
::
write
(
CONFIG_FILE_NAME
,
toml
::
to_string_pretty
(
&
robo_toml
)
?
)
?
;
std
::
fs
::
write
(
"src/main.rs"
,
prepare_main
(
TPL_DEFAULT_RS
,
&
robo_features
))
?
;
std
::
fs
::
write
(
"src/main.rs"
,
prepare_main
(
TPL_DEFAULT_RS
,
&
robo_features
))
?
;
println!
(
"Project created: {}"
,
opts
.name
.green
()
.bold
());
println!
(
"Project created: {}"
,
opts
.name
.green
()
.bold
());
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论