cyfs_core/app/
app_cmd.rs

1use crate::codec::*;
2use crate::coreobj::CoreObjectType;
3use crate::DecAppId;
4use chrono::{DateTime, Local};
5use cyfs_base::*;
6use serde::Serialize;
7use std::collections::HashMap;
8
9//AppCmd只提供基本的操作,升级降级可以由客户端拼出来。(先uninstall,再install)
10#[derive(Clone, Debug, ProtobufTransform, Serialize)]
11#[cyfs_protobuf_type(crate::codec::protos::AddApp)]
12pub struct AddApp {
13    pub app_owner_id: Option<ObjectId>,
14}
15
16#[derive(Clone, Debug, ProtobufTransform, Serialize)]
17#[cyfs_protobuf_type(crate::codec::protos::InstallApp)]
18pub struct InstallApp {
19    pub ver: String,
20    pub run_after_install: bool,
21}
22#[derive(Clone, Debug, ProtobufEncode, ProtobufDecode, ProtobufTransformType, Serialize)]
23#[cyfs_protobuf_type(crate::codec::protos::ModifyAppPermission)]
24pub struct ModifyAppPermission {
25    pub permission: HashMap<String, bool>,
26}
27
28impl ProtobufTransform<protos::ModifyAppPermission> for ModifyAppPermission {
29    fn transform(value: protos::ModifyAppPermission) -> BuckyResult<Self> {
30        let mut permission = HashMap::new();
31        for item in &value.permission {
32            permission.insert(item.key.clone(), item.value);
33        }
34        Ok(Self { permission })
35    }
36}
37
38impl ProtobufTransform<&ModifyAppPermission> for protos::ModifyAppPermission {
39    fn transform(value: &ModifyAppPermission) -> BuckyResult<Self> {
40        let mut permission = vec![];
41        let tree_map: std::collections::BTreeMap<String, bool> =
42            value.permission.clone().into_iter().collect();
43        for (key, value) in tree_map {
44            permission.push(protos::StringBoolMapItem { key, value })
45        }
46        Ok(Self { permission })
47    }
48}
49
50#[derive(Copy, Clone, Debug, ProtobufEncode, ProtobufDecode, ProtobufTransformType, Serialize)]
51#[cyfs_protobuf_type(crate::codec::protos::AppQuota)]
52pub struct AppQuota {
53    pub mem: i64,
54    pub disk_space: i64,
55    pub cpu: i64,
56}
57
58impl ProtobufTransform<protos::AppQuota> for AppQuota {
59    fn transform(value: protos::AppQuota) -> BuckyResult<Self> {
60        Ok(Self {
61            mem: value.mem.parse::<i64>()?,
62            disk_space: value.disk_space.parse::<i64>()?,
63            cpu: value.cpu.parse::<i64>()?,
64        })
65    }
66}
67
68impl ProtobufTransform<&AppQuota> for protos::AppQuota {
69    fn transform(value: &AppQuota) -> BuckyResult<Self> {
70        Ok(Self {
71            mem: value.mem.to_string(),
72            disk_space: value.disk_space.to_string(),
73            cpu: value.cpu.to_string(),
74        })
75    }
76}
77
78#[derive(Clone, Debug, ProtobufTransformType, Serialize)]
79#[cyfs_protobuf_type(crate::codec::protos::CmdCode)]
80pub enum CmdCode {
81    Add(AddApp),
82    Remove,
83    Install(InstallApp),
84    Uninstall,
85    Start,
86    Stop,
87    SetPermission(ModifyAppPermission),
88    SetQuota(AppQuota),
89    SetAutoUpdate(bool),
90    Unknown,
91}
92
93// impl fmt::Display for CmdCode {
94//     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95//         match self {
96//             &CmdCode::Add(add_app) => write!(f, "Init"),
97//             &CmdCode::Installing => write!(f, "Installing"),
98//             &CmdCode::InstallFailed => write!(f, "InstallFailed"),
99//             &CmdCode::NoService => write!(f, "NoService"),
100//             &CmdCode::Stopping => write!(f, "Stopping"),
101//             &CmdCode::Stop => write!(f, "Stop"),
102//             &CmdCode::StopFailed => write!(f, "StopFailed"),
103//             &CmdCode::Starting => write!(f, "Starting"),
104//             &CmdCode::Running => write!(f, "Running"),
105//             &CmdCode::StartFailed => write!(f, "StartFailed"),
106//             &CmdCode::Uninstalling => write!(f, "Uninstalling"),
107//         }
108//     }
109// }
110
111impl ProtobufTransform<protos::CmdCode> for CmdCode {
112    fn transform(value: protos::CmdCode) -> BuckyResult<Self> {
113        let ret = match value.code {
114            0 => Self::Add(ProtobufTransform::transform(value.add_app.unwrap())?),
115            1 => Self::Remove,
116            2 => Self::Install(ProtobufTransform::transform(value.install_app.unwrap())?),
117            3 => Self::Uninstall,
118            4 => Self::Start,
119            5 => Self::Stop,
120            6 => Self::SetPermission(ProtobufTransform::transform(value.app_permission.unwrap())?),
121            7 => Self::SetQuota(ProtobufTransform::transform(value.app_quota.unwrap())?),
122            8 => Self::SetAutoUpdate(value.auto_update.unwrap()),
123            v @ _ => {
124                warn!("unknown app cmd code: {}", v);
125                Self::Unknown
126            }
127        };
128
129        Ok(ret)
130    }
131}
132
133impl ProtobufTransform<&CmdCode> for protos::CmdCode {
134    fn transform(value: &CmdCode) -> BuckyResult<Self> {
135        let mut ret = Self {
136            code: -1,
137            add_app: None,
138            install_app: None,
139            app_permission: None,
140            app_quota: None,
141            auto_update: None,
142        };
143        match value {
144            CmdCode::Add(v) => {
145                ret.code = 0;
146                ret.add_app = Some(ProtobufTransform::transform(v)?);
147            }
148            CmdCode::Remove => {
149                ret.code = 1;
150            }
151            CmdCode::Install(v) => {
152                ret.code = 2;
153                ret.install_app = Some(ProtobufTransform::transform(v)?);
154            }
155            CmdCode::Uninstall => {
156                ret.code = 3;
157            }
158            CmdCode::Start => {
159                ret.code = 4;
160            }
161            CmdCode::Stop => {
162                ret.code = 5;
163            }
164            CmdCode::SetPermission(v) => {
165                ret.code = 6;
166                ret.app_permission = Some(ProtobufTransform::transform(v)?);
167            }
168            CmdCode::SetQuota(v) => {
169                ret.code = 7;
170                ret.app_quota = Some(ProtobufTransform::transform(v)?);
171            }
172            CmdCode::SetAutoUpdate(v) => {
173                ret.code = 8;
174                ret.auto_update = Some(*v);
175            }
176            _ => {
177                ret.code = -1;
178            }
179        }
180        Ok(ret)
181    }
182}
183
184#[derive(Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, Serialize)]
185#[cyfs_protobuf_type(crate::codec::protos::AppCmdDesc)]
186pub struct AppCmdDesc {
187    pub app_id: DecAppId,
188    pub cmd_code: CmdCode,
189}
190
191impl DescContent for AppCmdDesc {
192    fn obj_type() -> u16 {
193        CoreObjectType::AppCmd as u16
194    }
195
196    fn format(&self) -> u8 {
197        OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF
198    }
199
200    type OwnerType = Option<ObjectId>;
201    type AreaType = SubDescNone;
202    type AuthorType = SubDescNone;
203    type PublicKeyType = SubDescNone;
204}
205
206#[derive(Clone, Default, ProtobufEmptyEncode, ProtobufEmptyDecode, Serialize)]
207pub struct AppCmdBody {}
208
209impl BodyContent for AppCmdBody {
210    fn format(&self) -> u8 {
211        OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF
212    }
213}
214
215type AppCmdType = NamedObjType<AppCmdDesc, AppCmdBody>;
216type AppCmdBuilder = NamedObjectBuilder<AppCmdDesc, AppCmdBody>;
217
218pub type AppCmdId = NamedObjectId<AppCmdType>;
219pub type AppCmd = NamedObjectBase<AppCmdType>;
220
221pub trait AppCmdObj {
222    fn app_id(&self) -> &DecAppId;
223    fn cmd(&self) -> &CmdCode;
224
225    fn add(owner: ObjectId, id: DecAppId, app_owner: Option<ObjectId>) -> Self;
226    fn remove(owner: ObjectId, id: DecAppId) -> Self;
227    fn install(owner: ObjectId, id: DecAppId, version: &str, run_after_install: bool) -> Self;
228    fn uninstall(owner: ObjectId, id: DecAppId) -> Self;
229    fn start(owner: ObjectId, id: DecAppId) -> Self;
230    fn stop(owner: ObjectId, id: DecAppId) -> Self;
231    //permission参数: String表示语义路径,bool表示是否授权,如果permission有改变,app会重启并应用新的权限
232    fn set_permission(owner: ObjectId, id: DecAppId, permission: ModifyAppPermission) -> Self;
233    //quota参数: String表示语义路径,bool表示是否授权,如果permission有改变,app会重启并应用新的权限
234    fn set_quota(owner: ObjectId, id: DecAppId, quota: AppQuota) -> Self;
235    fn set_auto_update(owner: ObjectId, id: DecAppId, auto_update: bool) -> Self;
236
237    fn output(&self) -> String;
238}
239
240struct AppCmdHelper {}
241
242impl AppCmdHelper {
243    fn create(owner: ObjectId, app_id: DecAppId, cmd_code: CmdCode) -> AppCmd {
244        let desc = AppCmdDesc { app_id, cmd_code };
245
246        AppCmdBuilder::new(desc, AppCmdBody {})
247            .owner(owner)
248            .option_create_time(None)
249            .build()
250    }
251}
252
253impl AppCmdObj for AppCmd {
254    fn app_id(&self) -> &DecAppId {
255        &self.desc().content().app_id
256    }
257
258    fn cmd(&self) -> &CmdCode {
259        &self.desc().content().cmd_code
260    }
261
262    fn add(owner: ObjectId, id: DecAppId, app_owner: Option<ObjectId>) -> Self {
263        let cmd = CmdCode::Add(AddApp {
264            app_owner_id: app_owner,
265        });
266        AppCmdHelper::create(owner, id, cmd)
267    }
268
269    fn remove(owner: ObjectId, id: DecAppId) -> Self {
270        AppCmdHelper::create(owner, id, CmdCode::Remove)
271    }
272
273    fn install(owner: ObjectId, id: DecAppId, version: &str, run_after_install: bool) -> Self {
274        let cmd = CmdCode::Install(InstallApp {
275            ver: version.to_owned(),
276            run_after_install,
277        });
278
279        AppCmdHelper::create(owner, id, cmd)
280    }
281
282    fn uninstall(owner: ObjectId, id: DecAppId) -> Self {
283        AppCmdHelper::create(owner, id, CmdCode::Uninstall)
284    }
285
286    fn start(owner: ObjectId, id: DecAppId) -> Self {
287        AppCmdHelper::create(owner, id, CmdCode::Start)
288    }
289
290    fn stop(owner: ObjectId, id: DecAppId) -> Self {
291        AppCmdHelper::create(owner, id, CmdCode::Stop)
292    }
293
294    fn set_permission(owner: ObjectId, id: DecAppId, permission: ModifyAppPermission) -> Self {
295        AppCmdHelper::create(owner, id, CmdCode::SetPermission(permission))
296    }
297
298    fn set_quota(owner: ObjectId, id: DecAppId, quota: AppQuota) -> Self {
299        AppCmdHelper::create(owner, id, CmdCode::SetQuota(quota))
300    }
301
302    fn set_auto_update(owner: ObjectId, id: DecAppId, auto_update: bool) -> Self {
303        AppCmdHelper::create(owner, id, CmdCode::SetAutoUpdate(auto_update))
304    }
305
306    fn output(&self) -> String {
307        let app_id = self.app_id();
308        let cmd_code = self.cmd();
309        let create_time = bucky_time_to_system_time(self.desc().create_time());
310        let create_time: DateTime<Local> = create_time.into();
311        format!(
312            "[AppCmd] appid:{}, cmd: {:?}, create time:{}",
313            app_id,
314            cmd_code,
315            create_time.format("[%Y-%m-%d %H:%M:%S.%3f]")
316        )
317    }
318}