Compare commits

..

29 Commits

Author SHA1 Message Date
algotao
232a2c9d2e 更新docker版本 2026-01-19 14:56:22 +08:00
algotao
5cf860acfb 支持ds重置(当前限geo) 2026-01-19 14:54:18 +08:00
algotao
369023b81d 优化error输出 2026-01-11 17:24:11 +08:00
algotao
5e102ea8e7 script run调整为script debug;优化错误信息输出 2026-01-11 17:23:51 +08:00
algotao
970d9db8da 修改测试数据集 2026-01-08 14:16:41 +08:00
algotao
d4bf3297d4 改良写入字段,减少使用者失误 2025-12-16 17:19:06 +08:00
algotao
9a892eb533 daemon模式写入序修正 2025-12-13 21:07:12 +08:00
algotao
765e75937d 实验报表授权、GEO支持 2025-12-13 09:16:21 +08:00
algotao
cbbeb04ee5 更新docker版本 2025-11-23 12:05:58 +08:00
algotao
c9d794430e 调整授权功能 2025-11-23 12:01:33 +08:00
algotao
4575590faa 增加grant的ds字段 2025-11-19 12:32:36 +08:00
algotao
25715910cb 调整lua proto编号 2025-11-16 16:10:43 +08:00
algotao
430ce87959 支持数据授权管理功能 2025-11-14 19:24:18 +08:00
algotao
85f64c16b4 修正help文本 2025-11-14 16:52:36 +08:00
algotao
00fb793d9a 支持策略创建、删除,脚本列表、创建、删除、获取、使用 2025-11-10 15:57:31 +08:00
algotao
f9b7857b24 修改输出格式 2025-11-05 17:27:23 +08:00
algotao
c430544562 修改编译镜像引用 2025-11-05 11:35:01 +08:00
e48a840959 修正 2025-11-04 21:25:50 +08:00
algotao
2bf848f79b 改字 2025-11-03 10:21:20 +08:00
4008b44a77 支持鸿蒙系统 2025-10-21 16:29:01 +08:00
a8a54cc1bc 修正groupby字段读取逻辑 2025-10-18 15:11:50 +08:00
0230085a70 优化proto字段名称 2025-10-16 12:44:37 +08:00
df62e4fae6 支持实验数据拉取 2025-10-16 10:09:20 +08:00
algotao
d7ab7b5156 saastool增加docker/daemon模式 2025-09-24 18:38:03 +08:00
algotao
a88c5c6e3f 展示存储版本 2025-09-16 18:53:54 +08:00
algotao
ca81fba208 支持显示运行进度 2025-09-16 10:49:54 +08:00
algotao
fade72885f 去除u8区的高区操作功能 2025-09-09 11:03:25 +08:00
algotao
fff023b56d 增加lua调试功能 2025-09-02 15:45:56 +08:00
algotao
ed06c46bde 更换包域名 2025-08-30 15:59:39 +08:00
62 changed files with 5740 additions and 843 deletions

2
.gitignore vendored
View File

@@ -1,3 +1,5 @@
vendor/ vendor/
*.out *.out
build/ build/
*.lua
*.bak

12
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,12 @@
{
"go.useLanguageServer": true,
"[go]": {
"editor.insertSpaces": true,
"editor.tabSize": 4,
"editor.indentSize": 4
},
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit"
}
}

3286
cmd.pb.go

File diff suppressed because it is too large Load Diff

344
cmd.proto
View File

@@ -2,7 +2,7 @@ syntax = "proto3";
package saasapi; package saasapi;
option go_package = "e.coding.net/rta/public/saasapi"; option go_package = "git.algo.com.cn/public/saasapi";
// SaasReq 命令请求 // SaasReq 命令请求
message SaasReq { message SaasReq {
@@ -12,6 +12,7 @@ message SaasReq {
Read read = 10; // 批量读取 Read read = 10; // 批量读取
Write write = 11; // 批量写入 Write write = 11; // 批量写入
ColumnWrite column_write = 12; // 全量列式写入 ColumnWrite column_write = 12; // 全量列式写入
ResetDs reset_ds = 13; // 清空数据区
Task task_create = 20; // 任务创建 Task task_create = 20; // 任务创建
TaskList task_list = 21; // 列出任务 TaskList task_list = 21; // 列出任务
@@ -20,12 +21,28 @@ message SaasReq {
TaskInfo task_info = 24; // 任务详情 TaskInfo task_info = 24; // 任务详情
TargetList target_list = 50; // 列出策略及绑定 TargetList target_list = 50; // 列出策略及绑定
TargetCreate target_create = 51; // 创建策略
TargetDelete target_delete = 52; // 删除策略
BindSet bind_set = 61; // 设置绑定 BindSet bind_set = 61; // 设置绑定
BindDelete bind_delete = 62; // 解除绑定 BindDelete bind_delete = 62; // 解除绑定
ScriptRun script_run = 90; // 运行脚本 GrantList grant_list = 70; // 列出数据授权
ScriptUpdate script_update = 91; // 脚本升级 Grant grant_add = 71; // 增加数据授权
Grant grant_delete = 72; // 删除数据授权
ScriptDebug script_debug = 90; // 调试脚本
ScriptCreate script_create = 91; // 脚本创建
ScriptList script_list = 92; // 列出脚本
ScriptDelete script_delete = 93; // 删除脚本
ScriptGet script_get = 94; // 获取脚本内容
ScriptUse script_use = 95; // 使用脚本
ExpList exp_list = 100; // 列出实验
ExpGet exp_get = 101; // 获取实验报表
ExpGrantList exp_grant_list = 102; // 列出访问实验报表授权
ExpGrant exp_grant_add = 103; // 授权他人访问实验报表
ExpGrant exp_grant_delete = 104; // 取消他人访问实验报表
} }
} }
@@ -57,29 +74,30 @@ message Write {
// WriteItem 写入命令 // WriteItem 写入命令
message WriteItem { message WriteItem {
string userid = 1; // 用户ID string userid = 1; // 用户ID
Bytes write_bytes = 2; // byte区域 Bytes write_bytes = 2 [deprecated = true]; // byte区域。!!!弃用请使用bytes_kv
Uint32s write_uint32s = 3; // uint32区域 Uint32s write_uint32s = 3 [deprecated = true]; // uint32区域。!!!弃用请使用uint32s_kv
FlagsWithExpire write_flags_with_expire = 4; // 标志位区域 FlagsWithExpire write_flags_with_expire = 4 [deprecated = true]; // 标志位区域。!!!弃用请使用flags_with_expire_kv
map<uint32, uint32> bytes_kv = 5; // 写入uint8key为1-64索引值value为0-255数值。index/value超限会丢弃
map<uint32, uint32> uint32s_kv = 6; // 写入uint32key为1-8索引值value为uint32数值。index超限会丢弃
map<uint32, FlagWithExpire> flags_with_expire_kv = 7; // 写入标志位key为1-4索引值index超限会丢弃
} }
// Bytes 写入byte区域 // Bytes 写入uint8区域
message Bytes { message Bytes {
bytes bytes = 1; // 写入的byte bytes bytes = 1; // 写入的uint8
uint64 index_1 = 2; // 写入byte的索引值(0..63) uint64 index_1 = 2; // 写入uint8的索引值(0..63)
uint64 index_2 = 3; // 写入byte的索引值(64..127)
} }
// Uint32s 写入uint32区域 // Uint32s 写入uint32区域
message Uint32s { message Uint32s {
repeated uint32 uint32s = 1; // 写入的uint32 repeated uint32 uint32s = 1; // 写入的uint32
uint64 index_1 = 2; // 写入uint32的索引值(0..15) 最多 16 uint64 index_1 = 2; // 写入uint32的索引值(0..7) 最多 8
//uint64 index_2 = 3; // 写入uint32的索引值(当前不支持)
} }
// FlagsWithExpire 写入标志位区域 // FlagsWithExpire 写入标志位区域
message FlagsWithExpire { message FlagsWithExpire {
repeated FlagWithExpire flags_with_expire = 1; // 写入的标志位 repeated FlagWithExpire flags_with_expire = 1; // 写入的标志位
uint64 index_1 = 2; // 写入标志位的索引值 uint64 index_1 = 2; // 写入标志位的索引值(0..3) 最多 4 个
} }
// FlagWithExpire 标志位 // FlagWithExpire 标志位
@@ -98,6 +116,11 @@ message ColumnWrite {
FlagsWithExpire write_flags_with_expire = 5; // 标志位区域 FlagsWithExpire write_flags_with_expire = 5; // 标志位区域
} }
// ResetDs 清空数据区命令
message ResetDs {
string dataspace_id = 1; // 数据空间ID
}
message Task { message Task {
string dataspace_id = 1; // 数据空间ID string dataspace_id = 1; // 数据空间ID
string appid = 2; // 小程序/小游戏/公众号/视频号的appid string appid = 2; // 小程序/小游戏/公众号/视频号的appid
@@ -112,6 +135,8 @@ message Task {
string create_time = 10; // 创建时间 string create_time = 10; // 创建时间
string run_time = 11; // 运行时间 string run_time = 11; // 运行时间
string finish_time = 12; // 完成时间 string finish_time = 12; // 完成时间
uint32 running_block = 13; // 正在运行的块编号
uint32 total_block = 14; // 总块数
TaskStatus status = 15; // 任务状态 TaskStatus status = 15; // 任务状态
} }
@@ -156,6 +181,17 @@ message TargetList {
bool list_bind = 2; // 是否同时列出绑定信息 bool list_bind = 2; // 是否同时列出绑定信息
} }
// TargetCreate 创建策略
message TargetCreate {
string target_id = 1; // 策略ID
string target_description = 2; // 策略描述
}
// TargetDelete 删除策略
message TargetDelete {
string target_id = 1; // 策略ID
}
// BindSet 设置绑定 // BindSet 设置绑定
message BindSet { message BindSet {
repeated Bind binds = 2; // 设置绑定内容 repeated Bind binds = 2; // 设置绑定内容
@@ -166,8 +202,20 @@ message BindDelete {
repeated Bind binds = 2; // 解除绑定内容 repeated Bind binds = 2; // 解除绑定内容
} }
// ScriptRun 运行脚本 // GrantList 列出数据授权
message ScriptRun { message GrantList {
}
// Grant 数据授权信息
message Grant {
uint32 target_account_id = 1; // sRTA授权目标账号ID
string grant_index = 2; // 授权索引。格式为 "index1, index2, index55-index64",例如 "1, 2, 55-64"
uint32 dataspace_id = 3; // 授权数据空间ID数字型
}
// ScriptDebug 调试脚本
message ScriptDebug {
string lua_script = 1; // 要调试的lua脚本 string lua_script = 1; // 要调试的lua脚本
string server_did = 2; // 将从服务端读取该DID下的数据 string server_did = 2; // 将从服务端读取该DID下的数据
string appid = 3; // 小程序/小游戏/公众号/视频号的appid string appid = 3; // 小程序/小游戏/公众号/视频号的appid
@@ -175,8 +223,61 @@ message ScriptRun {
OS os = 5; // 操作系统 OS os = 5; // 操作系统
} }
// ScriptUpdate 升级脚本 // ScriptCreate 创建脚本
message ScriptUpdate { message ScriptCreate {
string lua_name = 1; // 要上传的脚本名称
string lua_script = 2; // 要调试的lua脚本
}
// ScriptList 列出脚本
message ScriptList {
}
// ScriptDelete 删除脚本
message ScriptDelete {
string lua_name = 1; // 要删除的脚本名称
}
// ScriptGet 获取脚本
message ScriptGet {
string lua_name = 1; // 要获取的脚本名称
}
// ScriptUse 使用脚本
message ScriptUse {
string lua_name = 1; // 要使用的脚本名称
}
// ExpList 列出实验
message ExpList {
}
// ExpGet 获取实验报表
// select base_fields, {EXT_FIELDS}
// where day between {WHERE_BEGIN_DAY} and {WHERE_END_DAY}
// and expid in {WHERE_EXP_ID}
// and target = {WHERE_TARGET}
// and advertiser_id in {WHERE_ADVERTISER_ID}
// group by {GROUP_BY}
message ExpGet {
repeated string ext_fields = 1; // 扩展字段(除基础字段必然输出外,其余字段需在这里填写,也可以使用*输出全部扩展字段)
uint64 where_begin_day = 10; // 起始日期
uint64 where_end_day = 11; // 结束日期
repeated uint32 where_bucket_id = 12; // 实验ID(1-10)
string where_target = 13; // 策略ID
repeated uint64 where_advertiser_id = 14; // 广告主ID
repeated string group_by = 20; // 当前支持广告主ID(advertiser_id)
uint32 total_flag = 30; // 是否汇总0=不汇总1=汇总
}
message ExpGrantList {
}
message ExpGrant {
uint32 target_account_id = 1; // sRTA授权目标账号ID
} }
// SaasRes 命令返回 // SaasRes 命令返回
@@ -188,6 +289,7 @@ message SaasRes {
ReadRes read_res = 10; // 读取命令返回 ReadRes read_res = 10; // 读取命令返回
WriteRes write_res = 11; // 写入命令返回 WriteRes write_res = 11; // 写入命令返回
ResetDsRes reset_ds_res = 13; // 清空数据区命令返回
Task task_create_res = 20; // 创建任务返回状态 Task task_create_res = 20; // 创建任务返回状态
TaskListRes task_list_res = 21; // 任务列表返回状态 TaskListRes task_list_res = 21; // 任务列表返回状态
@@ -196,18 +298,42 @@ message SaasRes {
Task task_info_res = 24; // 任务详情返回状态 Task task_info_res = 24; // 任务详情返回状态
TargetListRes target_list_res = 50; // 列出策略及绑定返回状态 TargetListRes target_list_res = 50; // 列出策略及绑定返回状态
TargetCreateRes target_create_res = 51; // 创建策略返回状态
TargetDeleteRes target_delete_res = 52; // 删除策略返回状态
BindSetRes bind_set_res = 61; // 设置绑定返回状态 BindSetRes bind_set_res = 61; // 设置绑定返回状态
BindDeleteRes bind_delete_res = 62; // 删除绑定返回状态 BindDeleteRes bind_delete_res = 62; // 删除绑定返回状态
ScriptRunRes script_run_res = 90; // 运行脚本返回 GrantListRes grant_list_res = 70; // 列出数据授权返回状态
ScriptUpdateRes script_update_res = 91; // 升级脚本返回 Grant grant_add_res = 71; // 增加数据授权返回状态
Grant grant_delete_res = 72; // 删除数据授权返回状态
ScriptDebugRes script_debug_res = 90; // 调试脚本返回
ScriptCreateRes script_create_res = 91; // 创建脚本返回
ScriptListRes script_list_res = 92; // 列出脚本返回
ScriptDeleteRes script_delete_res = 93; // 删除脚本返回
ScriptGetRes script_get_res = 94; // 获取脚本返回
ScriptUseRes script_use_res = 95; // 使用脚本返回
ExpListRes exp_list_res = 100; // 实验列表返回
ExpGetRes exp_get_res = 101; // 实验报表返回
ExpGrantListRes exp_grant_list_res = 102; // 实验授权列表返回
ExpGrant exp_grant_add_res = 103; // 增加实验授权返回
ExpGrant exp_grant_delete_res = 104; // 实验解除授权返回
} }
} }
message DataSpace {
repeated string did = 1; // 设备ID区
repeated string wuid = 2; // OpenID区
repeated string geo = 7; // GEO区
repeated string geoip = 8; // GEOIP区
repeated string geofac = 9; // GEOFAC区(经常活动城市)
}
// InfoRes 账号信息返回 // InfoRes 账号信息返回
message InfoRes { message InfoRes {
repeated string dataspace_id = 1; // 可用数据区列表 DataSpace dataspace = 1; // 可用数据区列表
repeated string target_id = 2; // 策略ID列表 repeated string target_id = 2; // 策略ID列表
} }
@@ -216,7 +342,7 @@ message InfoRes {
message ReadRes { message ReadRes {
uint32 succ_cmd_count = 1; // 成功的命令数量 uint32 succ_cmd_count = 1; // 成功的命令数量
uint32 fail_cmd_count = 2; // 失败的命令数量 uint32 fail_cmd_count = 2; // 失败的命令数量
repeated ValueItem cmd_res = 3; // 返回的命令 repeated ValueItem cmd_res = 3 ; // 返回的命令
} }
// WriteRes 写记录返回 // WriteRes 写记录返回
@@ -230,10 +356,19 @@ message WriteRes {
message ValueItem { message ValueItem {
uint32 cmd_index = 1; // 命令索引 uint32 cmd_index = 1; // 命令索引
CmdErrorCode cmd_code = 2; // 状态 CmdErrorCode cmd_code = 2; // 状态
bytes bytes = 3; // byte区域 bytes bytes = 3 [deprecated = true]; // byte区域。!!!弃用
repeated uint32 uint32s = 4; // uint32区域 repeated uint32 uint32s = 4 [deprecated = true]; // uint32区域。!!!弃用
repeated FlagWithExpire flags_with_expire = 5; // 标志位区域 repeated FlagWithExpire flags_with_expire = 5 [deprecated = true]; // 标志位区域。!!!弃用
uint32 last_modify_time = 6; // 最后修改时间 uint32 last_modify_time = 6; // 最后修改时间
uint32 version = 7; // 存储版本
map<uint32, uint32> bytes_kv = 8; // byte区域
map<uint32, uint32> uint32s_kv = 9; // uint32区域
map<uint32, FlagWithExpire> flags_with_expire_kv = 10; // 标志位区域
}
// ResetDsRes 清空数据区返回
message ResetDsRes {
string dataspace_id = 1; // 数据空间ID
} }
// TaskListRes 任务列表返回 // TaskListRes 任务列表返回
@@ -246,67 +381,159 @@ message TargetListRes {
map<string, Binds> target_list = 1; // 绑定列表 map<string, Binds> target_list = 1; // 绑定列表
} }
// TargetCreateRes 策略创建返回
message TargetCreateRes {
string target_id = 1; // 策略ID
string target_description = 2; // 策略描述
}
// TargetDeleteRes 策略创建返回
message TargetDeleteRes {
string target_id = 1; // 策略ID
string target_description = 2; // 策略描述
}
message Binds { message Binds {
repeated Bind binds = 1; repeated Bind binds = 1; // 绑定列表
} }
// Bind 绑定信息 // Bind 绑定信息
message Bind { message Bind {
int64 bind_id = 1; //绑定的ID int64 bind_id = 1; // 绑定的ID
BindType bind_type = 2; //绑定类型 BindType bind_type = 2; // 绑定类型
string target_id = 3; //策略ID string target_id = 3; // 策略ID
int64 account_id = 4; //广告主ID int64 account_id = 4; // 广告主ID
BindSourceType bind_source = 5; //绑定操作来源 BindSourceType bind_source = 5; // 绑定操作来源
} }
// BindType 绑定类型 // BindType 绑定类型
enum BindType { enum BindType {
UnknownBindType = 0; UnknownBindType = 0;
AdgroupId = 1; //广告 AdgroupId = 1; // 广告
AccountId = 3; //广告主 AccountId = 3; // 广告主
} }
// BindSourceType 绑定操作来源 // BindSourceType 绑定操作来源
enum BindSourceType { enum BindSourceType {
DefaultBindSourceType = 0; //广告主或未填写 DefaultBindSourceType = 0; // 广告主或未填写
ThirdPartyApi = 1; //第三方API ThirdPartyApi = 1; // 第三方API
ADQ = 2; //ADQ平台 ADQ = 2; // ADQ平台
MP = 3; //MP平台 MP = 3; // MP平台
MktApi = 4; //MarketingAPI MktApi = 4; // MarketingAPI
} }
// BindSetRes 设置绑定返回 // BindSetRes 设置绑定返回
message BindSetRes { message BindSetRes {
int32 success_num = 1; //成功数 int32 success_num = 1; // 成功数
int32 error_num = 2; //错误数 int32 error_num = 2; // 错误数
repeated BindError errors = 3; //绑定错误的记录 repeated BindError errors = 3; // 绑定错误的记录
} }
// BindDeleteRes 删除绑定返回 // BindDeleteRes 删除绑定返回
message BindDeleteRes { message BindDeleteRes {
int32 success_num = 1; //成功数 int32 success_num = 1; // 成功数
int32 error_num = 2; //错误数 int32 error_num = 2; // 错误数
repeated BindError errors = 3; //绑定错误的记录 repeated BindError errors = 3; // 绑定错误的记录
} }
// BindError 绑定错误信息 // BindError 绑定错误信息
message BindError { message BindError {
int64 bind_id = 1; //错误绑定的绑定ID int64 bind_id = 1; // 错误绑定的绑定ID
int32 bind_type = 2; //绑定类型 int32 bind_type = 2; // 绑定类型
string reason = 3; //错误绑定原因 string reason = 3; // 错误绑定原因
} }
// GrantListRes 授权列表返回
message GrantListRes {
repeated Grant from = 1; // 被授权列表
repeated Grant to = 2; // 向外授权列表
}
// ScriptRunRes 运行脚本返回 // ScriptDebugRes 调试脚本返回
message ScriptRunRes { message ScriptDebugRes {
string print_output = 1; // print输出 string print_output = 1; // print输出
string error = 2; // 错误信息 string error_output = 2; // 错误信息
string targets_output = 3; // 策略输出 string targets_output = 3; // 策略输出
string dataspace_out = 4; // 数据区输出
} }
// ScriptUpdateRes 升级脚本返回 message ScriptInfo {
message ScriptUpdateRes { string lua_name = 1; // 脚本名称
string lua_script = 2; // 脚本内容
bool lua_checked = 3; // 脚本校验结果
bool lua_used = 4; // 脚本是否被使用
}
// ScriptCreateRes 创建脚本返回
message ScriptCreateRes {
ScriptInfo script_info = 1; // 脚本信息
}
// ScriptListRes 脚本列表返回
message ScriptListRes {
repeated ScriptInfo script_info = 1; // 脚本信息
}
// ScriptGetRes 获取脚本返回
message ScriptGetRes {
ScriptInfo script_info = 1; // 脚本信息
}
// ScriptDeleteRes 删除脚本返回
message ScriptDeleteRes {
ScriptInfo script_info = 1; // 脚本信息
}
// ScriptUseRes 使用脚本返回
message ScriptUseRes {
ScriptInfo script_info = 1; // 脚本信息
}
// ExpListRes 实验列表返回
message ExpListRes {
repeated ExpBucket buckets = 1; // 实验桶
}
message ExpBucket {
uint32 bucket_id = 1; // 分桶号
uint32 pt_exp_id = 2; // 平台实验ID
uint32 percent = 3; // 流量百分比
}
// ExpGetRes 实验报表返回
message ExpGetRes {
repeated ExpData exp_data = 1; // 实验数据
}
// ExpData 实验数据
message ExpData {
uint64 time = 1; // 日期
uint32 bucket_id = 2; // 分桶ID
ExpBaseFields base_fields = 3; // 基础字段
map <string, double> ext_fields = 4; // 扩展字段
map<string, uint64> group = 5; // 分组
}
// ExpBaseFields 基础实验字段
message ExpBaseFields {
double cost = 1; // 花费
int64 exposure = 2; // 曝光量
int64 click = 3; // 点击量
double cpm = 4; // 千次曝光价格
double cpc = 5; // 单次点击价格
double cpa = 6; // 单次转化成本
double ctr = 7; // 点击率
double cvr = 8; // 浅层转化率
double cvr_second = 9; // 深层转化率
int64 conversion = 10; // 浅层转化量
int64 conversion_second = 11; // 深层转化量
}
// ExpGrantListRes 授权列表返回
message ExpGrantListRes {
repeated ExpGrant from = 1; // 被授权列表
repeated ExpGrant to = 2; // 向外授权列表
} }
// ErrorCode 返回码 // ErrorCode 返回码
@@ -315,7 +542,7 @@ enum ErrorCode {
INVALID_ACCOUNT = 101; // Account不合法 INVALID_ACCOUNT = 101; // Account不合法
INVALID_TIMESTAMP = 102; // 头信息缺少时间戳或不正确 INVALID_TIMESTAMP = 102; // 头信息缺少时间戳或不正确
INVALID_SIGNATURE = 103; // 头信息缺少签名 INVALID_SIGNATURE = 103; // 头信息缺少签名
AUTH_FAIL = 104; // 签名验失败 AUTH_FAIL = 104; // 签名验失败
DISABLED_ACCOUNT = 105; // 账号已禁用 DISABLED_ACCOUNT = 105; // 账号已禁用
INVALID_CONTENT_TYPE = 110; // 非法的Content-Type INVALID_CONTENT_TYPE = 110; // 非法的Content-Type
READ_BODY = 111; // 读取 http body 失败 READ_BODY = 111; // 读取 http body 失败
@@ -342,12 +569,15 @@ enum ErrorCode {
CMD_ERROR = 202; // 命令行执行错误 CMD_ERROR = 202; // 命令行执行错误
API_ERROR = 301; // 调用内部API错误 API_ERROR = 301; // 调用内部API错误
PARAM_ERROR = 401; // 参数错误
} }
enum CmdErrorCode { enum CmdErrorCode {
OK = 0; // 成功 OK = 0; // 成功
} }
// TaskStatus 任务状态
enum TaskStatus { enum TaskStatus {
ALL = 0; // 全部 ALL = 0; // 全部
WAITING = 1; // 等待中 WAITING = 1; // 等待中
@@ -360,8 +590,16 @@ enum TaskStatus {
} }
enum OS { enum OS {
UNKNOWN = 0; OS_UNKNOWN = 0;
IOS = 1; IOS = 1;
ANDROID = 2; ANDROID = 2;
HARMONY = 7; //纯血鸿蒙
} }
// MAX 最大限定
enum MAX {
MAX_UNKNOWN = 0;
U8 = 64;
U32 = 8;
FLAG = 4;
}

View File

@@ -3,3 +3,5 @@ saastool
saastool_linux saastool_linux
*.toml *.toml
test/ test/
*.lua
test.txt

View File

@@ -2,7 +2,6 @@ package main
import ( import (
"fmt" "fmt"
"os"
"strings" "strings"
) )
@@ -20,10 +19,7 @@ func RunBind(args ...string) error {
case "delete": case "delete":
return RunBindDelete(args...) return RunBindDelete(args...)
default: default:
err := fmt.Errorf(`unknown command "%s"`+"\n"+`Run 'saastool bind help' for usage`, name) return fmt.Errorf(`Unknown command "%s"`+"\n"+`Run 'saastool bind help' for usage`, name)
fmt.Fprintln(os.Stderr, err)
return err
} }
} }

View File

@@ -4,12 +4,11 @@ import (
"flag" "flag"
"fmt" "fmt"
"net/http" "net/http"
"os"
"strconv" "strconv"
"strings" "strings"
"e.coding.net/rta/public/saasapi" "git.algo.com.cn/public/saasapi"
"e.coding.net/rta/public/saasapi/pkg/saashttp" "git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/protojson"
) )
@@ -26,8 +25,7 @@ func RunBindDelete(args ...string) error {
ids := paramIDs(fs) ids := paramIDs(fs)
if err := fs.Parse(args); err != nil { if err := fs.Parse(args); err != nil {
fmt.Fprintln(os.Stderr, "command line parse error", "err", err) return fmt.Errorf("Command line parse error: %w", err)
return err
} }
// 切割字符串 // 切割字符串
@@ -45,16 +43,14 @@ func RunBindDelete(args ...string) error {
for _, v := range idsSlice { for _, v := range idsSlice {
n, err := strconv.ParseInt(v, 10, 64) n, err := strconv.ParseInt(v, 10, 64)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "id parse error", "value", v, "err", err) return fmt.Errorf("Id parse error. value: %v. %w", v, err)
return err
} }
numIds = append(numIds, n) numIds = append(numIds, n)
} }
cfg, err := LoadConfigFile(*cfgFile) cfg, err := LoadConfigFile(*cfgFile)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "LoadConfigFile error", "err", err) return fmt.Errorf("LoadConfigFile error: %w", err)
return err
} }
bindDeleteParams := bindDeleteParams{ bindDeleteParams := bindDeleteParams{
@@ -87,15 +83,12 @@ func doBindDeleteAccount(p bindDeleteParams) error {
} }
res, err := p.saasHttp.BindDelete(saasReq) res, err := p.saasHttp.BindDelete(saasReq)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "submit Bind Delete error", "err", err) return fmt.Errorf("Submit Command error: %w", err)
return err
} }
if res.Code != saasapi.ErrorCode_SUCC { if res.Code != saasapi.ErrorCode_SUCC {
fmt.Fprintln(os.Stderr, "Bind Delete failed", "code", res.Code, "status", res.Status) return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
return nil
} }
bindRes := res.GetBindDeleteRes() bindRes := res.GetBindDeleteRes()

View File

@@ -4,12 +4,11 @@ import (
"flag" "flag"
"fmt" "fmt"
"net/http" "net/http"
"os"
"strconv" "strconv"
"strings" "strings"
"e.coding.net/rta/public/saasapi" "git.algo.com.cn/public/saasapi"
"e.coding.net/rta/public/saasapi/pkg/saashttp" "git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/protojson"
) )
@@ -26,8 +25,7 @@ func RunBindSetAccount(args ...string) error {
accounts := paramAccounts(fs) accounts := paramAccounts(fs)
if err := fs.Parse(args); err != nil { if err := fs.Parse(args); err != nil {
fmt.Fprintln(os.Stderr, "command line parse error", "err", err) return fmt.Errorf("Command line parse error: %w", err)
return err
} }
// 切割字符串 // 切割字符串
@@ -45,16 +43,14 @@ func RunBindSetAccount(args ...string) error {
for _, v := range idsSlice { for _, v := range idsSlice {
n, err := strconv.ParseInt(v, 10, 64) n, err := strconv.ParseInt(v, 10, 64)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "account parse error", "value", v, "err", err) return fmt.Errorf("Account parse error. value: %v. %w", v, err)
return err
} }
numAccounts = append(numAccounts, n) numAccounts = append(numAccounts, n)
} }
cfg, err := LoadConfigFile(*cfgFile) cfg, err := LoadConfigFile(*cfgFile)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "LoadConfigFile error", "err", err) return fmt.Errorf("LoadConfigFile error: %w", err)
return err
} }
bindSetAccountParams := bindSetAccountParams{ bindSetAccountParams := bindSetAccountParams{
@@ -89,19 +85,14 @@ func doBindSetAccount(p bindSetAccountParams) error {
} }
res, err := p.saasHttp.BindSet(saasReq) res, err := p.saasHttp.BindSet(saasReq)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "submit Bind Set error", "err", err) return fmt.Errorf("Submit Command error: %w", err)
return err
} }
if res.Code != saasapi.ErrorCode_SUCC { if res.Code != saasapi.ErrorCode_SUCC {
fmt.Fprintln(os.Stderr, "Bind Set failed", "code", res.Code, "status", res.Status) return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
return nil
} }
bindRes := res.GetBindSetRes() fmt.Printf("bind res: %v\n", protojson.Format(res.GetBindSetRes()))
fmt.Printf("bind res: %v\n", protojson.Format(bindRes))
return nil return nil
} }

View File

@@ -4,12 +4,11 @@ import (
"flag" "flag"
"fmt" "fmt"
"net/http" "net/http"
"os"
"strconv" "strconv"
"strings" "strings"
"e.coding.net/rta/public/saasapi" "git.algo.com.cn/public/saasapi"
"e.coding.net/rta/public/saasapi/pkg/saashttp" "git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/protojson"
) )
@@ -28,8 +27,7 @@ func RunBindSetAd(args ...string) error {
ads := paramAds(fs) ads := paramAds(fs)
if err := fs.Parse(args); err != nil { if err := fs.Parse(args); err != nil {
fmt.Fprintln(os.Stderr, "command line parse error", "err", err) return fmt.Errorf("Command line parse error: %w", err)
return err
} }
// 切割字符串 // 切割字符串
@@ -47,16 +45,14 @@ func RunBindSetAd(args ...string) error {
for _, v := range idsSlice { for _, v := range idsSlice {
n, err := strconv.ParseInt(v, 10, 64) n, err := strconv.ParseInt(v, 10, 64)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "account parse error", "value", v, "err", err) return fmt.Errorf("AD parse error. value: %v. %w", v, err)
return err
} }
numAds = append(numAds, n) numAds = append(numAds, n)
} }
cfg, err := LoadConfigFile(*cfgFile) cfg, err := LoadConfigFile(*cfgFile)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "LoadConfigFile error", "err", err) return fmt.Errorf("LoadConfigFile error: %w", err)
return err
} }
bindSetAdParams := bindSetAdParams{ bindSetAdParams := bindSetAdParams{
@@ -92,19 +88,14 @@ func doBindSetAd(p bindSetAdParams) error {
} }
res, err := p.saasHttp.BindSet(saasReq) res, err := p.saasHttp.BindSet(saasReq)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "submit Bind Set error", "err", err) return fmt.Errorf("Submit Command error: %w", err)
return err
} }
if res.Code != saasapi.ErrorCode_SUCC { if res.Code != saasapi.ErrorCode_SUCC {
fmt.Fprintln(os.Stderr, "Bind Set failed", "code", res.Code, "status", res.Status) return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
return nil
} }
bindRes := res.GetBindSetRes() fmt.Printf("bind res: %v\n", protojson.Format(res.GetBindSetRes()))
fmt.Printf("bind res: %v\n", protojson.Format(bindRes))
return nil return nil
} }

View File

@@ -1,7 +1,7 @@
package main package main
import ( import (
"e.coding.net/rta/public/saasapi/pkg/saashttp" "git.algo.com.cn/public/saasapi/pkg/saashttp"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
) )

View File

@@ -11,7 +11,7 @@ import (
"strings" "strings"
"sync" "sync"
"e.coding.net/rta/public/saasapi" "git.algo.com.cn/public/saasapi"
"google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/protojson"
) )
@@ -38,8 +38,7 @@ func RunConvert(args ...string) error {
destPath := paramDestPath(fs) destPath := paramDestPath(fs)
if err := fs.Parse(args); err != nil { if err := fs.Parse(args); err != nil {
fmt.Fprintln(os.Stderr, "command line parse error", "err", err) return fmt.Errorf("Command line parse error: %w", err)
return err
} }
if fs.NArg() > 0 || *mapCfgFile == "" || len(*sourcePath) == 0 || len(*destPath) == 0 { if fs.NArg() > 0 || *mapCfgFile == "" || len(*sourcePath) == 0 || len(*destPath) == 0 {
@@ -49,8 +48,7 @@ func RunConvert(args ...string) error {
mapCfg, err := LoadMapFile(*mapCfgFile) mapCfg, err := LoadMapFile(*mapCfgFile)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "LoadConfigFile error", "err", err) return fmt.Errorf("LoadMapFile error: %w", err)
return err
} }
convertParams := convertParams{ convertParams := convertParams{
@@ -236,11 +234,7 @@ func convertBatch(lines []string, convertParams convertParams, resultChan chan<-
saasWriteItem.WriteBytes = &saasapi.Bytes{} saasWriteItem.WriteBytes = &saasapi.Bytes{}
} }
saasWriteItem.WriteBytes.Bytes = append(saasWriteItem.WriteBytes.Bytes, *targetinfo.WriteByte) saasWriteItem.WriteBytes.Bytes = append(saasWriteItem.WriteBytes.Bytes, *targetinfo.WriteByte)
if targetinfo.WriteBytePos < 64 { saasWriteItem.WriteBytes.Index_1 |= 1 << targetinfo.WriteBytePos
saasWriteItem.WriteBytes.Index_1 |= 1 << targetinfo.WriteBytePos
} else if targetinfo.WriteBytePos < 128 {
saasWriteItem.WriteBytes.Index_2 |= 1 << (targetinfo.WriteBytePos - 64)
}
} }
if targetinfo.WriteUint32 != nil { if targetinfo.WriteUint32 != nil {

View File

@@ -0,0 +1,61 @@
package main
import (
"encoding/json"
"fmt"
"os"
"git.algo.com.cn/public/saasapi"
)
// MapConfig 配置
type MapConfig struct {
Targets map[string]*Target `json:"targets"`
}
// Target 配置
type Target struct {
WriteByte *byte `json:"write_byte"` // byte值
WriteBytePos uint32 `json:"write_byte_pos"` // byte写入位置
WriteUint32 *uint32 `json:"write_uint32"` // uint32值
WriteUint32Pos uint32 `json:"write_uint32_pos"` // uint32写入位置
WriteFlag *bool `json:"write_flag"` // 标志位
WriteExpire *uint32 `json:"write_expire"` // 过期时间
WriteFlagWithExpirePos uint32 `json:"write_flag_with_expire_pos"` // 标志与过期写入位置
}
// LoadConfigFile 加载配置文件
func LoadMapFile(filename string) (*MapConfig, error) {
// 打开文件
f, err := os.Open(filename)
if err != nil {
return nil, err
}
defer f.Close()
sc := &MapConfig{}
err = json.NewDecoder(f).Decode(sc)
if err != nil {
return nil, err
}
for targetName, targetInfo := range sc.Targets {
if targetInfo.WriteBytePos >= uint32(saasapi.MAX_U8) {
err = fmt.Errorf("%v WriteBytePos>MAX_U8 , current %v, MAX %v", targetName, targetInfo.WriteBytePos, uint32(saasapi.MAX_U8)-1)
break
}
if targetInfo.WriteUint32Pos >= uint32(saasapi.MAX_U32) {
err = fmt.Errorf("%v WriteUint32Pos>MAX_U32 , current %v, MAX %v", targetName, targetInfo.WriteUint32Pos, uint32(saasapi.MAX_U32)-1)
break
}
if targetInfo.WriteFlagWithExpirePos >= uint32(saasapi.MAX_FLAG) {
err = fmt.Errorf("%v WriteFlagWithExpirePos>MAX_FLAG , current %v, MAX %v", targetName, targetInfo.WriteFlagWithExpirePos, uint32(saasapi.MAX_FLAG)-1)
break
}
}
return sc, err
}

376
cmd/saastool/daemon.go Normal file
View File

@@ -0,0 +1,376 @@
package main
import (
"bufio"
"encoding/json"
"fmt"
"log/slog"
"net/http"
"net/url"
"os"
"strconv"
"strings"
"time"
"git.algo.com.cn/public/saasapi"
"git.algo.com.cn/public/saasapi/pkg/saashttp"
)
type Daemon struct {
saasHttp *saashttp.SaasClient
currTimeStamp uint32
}
type daemonPublicParams struct {
ds string
appid string
}
func RunDaemon(args ...string) error {
var err error
account := os.Getenv("SRTA_ACCOUNT")
token := os.Getenv("SRTA_TOKEN")
env := os.Getenv("SRTA_ENV")
slog.Info("Env", "SRTA_ACCOUNT", account)
slog.Info("Env", "SRTA_TOKEN", token)
slog.Info("Env", "SRTA_ENV", env)
if strings.TrimSpace(account) == "" {
err = fmt.Errorf("SRTA_ACCOUNT is empty")
slog.Error("Env", "err", err)
return err
}
if strings.TrimSpace(token) == "" {
err = fmt.Errorf("SRTA_TOKEN is empty")
slog.Error("Env", "err", err)
return err
}
apiurls := &saashttp.ApiUrls{}
switch strings.ToLower(env) {
case "demo":
apiurls.BaseUrl = "https://srta.algo.com.cn"
case "prd":
apiurls.BaseUrl = "https://api.rta.qq.com"
case "dev":
apiurls.BaseUrl = "http://localhost:8080"
default:
return fmt.Errorf("SRTA_ENV is not demo or prd")
}
mux := http.NewServeMux()
daemon := &Daemon{
saasHttp: &saashttp.SaasClient{
Client: &http.Client{},
ApiUrls: saashttp.InitAPIUrl(apiurls),
Auth: &saashttp.Auth{
Account: account,
Token: token,
},
},
}
mux.HandleFunc("/read", daemon.httpRead)
mux.HandleFunc("/write", daemon.httpWrite)
daemonPort := os.Getenv("SRTA_PORT")
if strings.TrimSpace(daemonPort) == "" {
daemonPort = "8080"
}
daemonPort = ":" + daemonPort
svrHttp := http.Server{
Addr: daemonPort,
Handler: mux,
}
slog.Info("Start running", "port", daemonPort)
err = svrHttp.ListenAndServe()
if err != nil {
slog.Error("failed", "err", err)
return err
}
return nil
}
func (d *Daemon) httpRead(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
w.Header().Set("Allow", http.MethodGet)
http.Error(w, fmt.Sprintf("Not support method: %s。Only GET。", r.Method), http.StatusMethodNotAllowed)
return
}
w.Header().Set("Content-Type", "application/json")
w.Header().Set("X-Content-Type-Options", "nosniff")
saasRes := &saasapi.SaasRes{}
defer func() {
json.NewEncoder(w).Encode(saasRes)
}()
params, err := d.parsePublicParams(r)
if err != nil {
saasRes.Code = saasapi.ErrorCode_CMD_ERROR
saasRes.Status = err.Error()
return
}
q := r.URL.Query()
userid := strings.TrimSpace(q.Get("userid"))
if len(userid) == 0 {
saasRes.Code = saasapi.ErrorCode_CMD_ERROR
saasRes.Status = "userid is null"
return
}
saasReadItems := []*saasapi.ReadItem{}
saasReadItems = append(saasReadItems, &saasapi.ReadItem{
Userid: userid,
})
saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_Read{
Read: &saasapi.Read{
DataspaceId: params.ds,
Appid: params.appid,
ReadItems: saasReadItems,
},
},
}
saasRes, err = d.saasHttp.Read(saasReq)
if err != nil {
saasRes.Code = saasapi.ErrorCode_CMD_ERROR
saasRes.Status = fmt.Sprintf("submit read error. %v", err)
return
}
}
func (d *Daemon) httpWrite(w http.ResponseWriter, r *http.Request) {
bPost := false
switch r.Method {
case http.MethodPost:
bPost = true
case http.MethodGet:
default:
w.Header().Set("Allow", http.MethodGet)
http.Error(w, fmt.Sprintf("Not support method: %s。Only GET/POST。", r.Method), http.StatusMethodNotAllowed)
return
}
w.Header().Set("Content-Type", "application/json")
w.Header().Set("X-Content-Type-Options", "nosniff")
saasRes := &saasapi.SaasRes{}
defer func() {
json.NewEncoder(w).Encode(saasRes)
}()
params, err := d.parsePublicParams(r)
if err != nil {
saasRes.Code = saasapi.ErrorCode_CMD_ERROR
saasRes.Status = err.Error()
return
}
q := r.URL.Query()
clear := q.Get("clear")
bClear := false
if len(clear) > 0 {
bClear, err = strconv.ParseBool(clear)
if err != nil {
saasRes.Code = saasapi.ErrorCode_CMD_ERROR
saasRes.Status = fmt.Sprintf("clear is error. %v", err)
return
}
}
d.currTimeStamp = uint32(time.Now().Unix())
writeItems, err := d.parseWriteParams(r, bPost)
if err != nil {
saasRes.Code = saasapi.ErrorCode_CMD_ERROR
saasRes.Status = fmt.Sprintf("write info error. %v", err)
return
}
write := &saasapi.Write{
DataspaceId: params.ds,
Appid: params.appid,
IsClearAllFirst: bClear,
}
saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_Write{
Write: write,
},
}
write.WriteItems = writeItems
saasRes, err = d.saasHttp.Write(saasReq)
if err != nil {
saasRes.Code = saasapi.ErrorCode_CMD_ERROR
saasRes.Status = fmt.Sprintf("submit write error. %v", err)
return
}
}
func (d *Daemon) parsePublicParams(r *http.Request) (*daemonPublicParams, error) {
params := &daemonPublicParams{}
q := r.URL.Query()
params.ds = strings.ToLower(strings.TrimSpace(q.Get("ds")))
switch params.ds {
case "did", "wuid", "geo", "geoip", "geofac":
default:
return nil, fmt.Errorf("ds must use did/wuid/geo/geoip/geofac. current is %v", params.ds)
}
params.appid = strings.TrimSpace(q.Get("appid"))
if params.ds == "wuid" && len(params.appid) == 0 {
return nil, fmt.Errorf("appid must exist when ds=wuid")
}
return params, nil
}
func (d *Daemon) parseWriteParams(r *http.Request, post bool) (writeItems []*saasapi.WriteItem, reterr error) {
writeItems = nil
lineNum := 0
if post {
scanner := bufio.NewScanner(r.Body)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
lineNum++
parsedQuery, err := url.ParseQuery(line)
if err != nil {
reterr = fmt.Errorf("parse error: %v", err)
return
}
item, err := d.parseQuery(parsedQuery, lineNum)
if err != nil {
reterr = fmt.Errorf("parse error: %v", err)
return
}
writeItems = append(writeItems, item)
}
} else {
item, err := d.parseQuery(r.URL.Query(), lineNum)
if err != nil {
reterr = fmt.Errorf("parse error: %v", err)
return
}
writeItems = append(writeItems, item)
}
return
}
func (d *Daemon) parseQuery(q url.Values, lineNum int) (writeItem *saasapi.WriteItem, reterr error) {
userid := strings.TrimSpace(q.Get("userid"))
if len(userid) == 0 {
reterr = fmt.Errorf("userid is null. line %v", lineNum)
return
}
writeItem = &saasapi.WriteItem{
Userid: userid,
BytesKv: map[uint32]uint32{},
Uint32SKv: map[uint32]uint32{},
FlagsWithExpireKv: map[uint32]*saasapi.FlagWithExpire{},
}
for key, value := range q {
parts := strings.Split(strings.ToLower(key), ".")
if len(parts) == 2 {
switch parts[0] {
case "u8":
index, err := strconv.ParseUint(parts[1], 10, 8)
if err != nil {
reterr = fmt.Errorf("param is error. line %v, param %v", lineNum, key)
return
}
if index == 0 || index > uint64(saasapi.MAX_U8) {
reterr = fmt.Errorf("param index is error. line %v, param %v, index %v", lineNum, key, index)
return
}
nValue, err := strconv.ParseUint(value[0], 10, 8)
if err != nil {
reterr = fmt.Errorf("param value is error. line %v, param %v, value %v", lineNum, key, value)
return
}
writeItem.BytesKv[uint32(index)] = uint32(nValue)
case "u32":
index, err := strconv.ParseUint(parts[1], 10, 8)
if err != nil {
reterr = fmt.Errorf("param is error. line %v, param %v", lineNum, key)
return
}
if index == 0 || index > uint64(saasapi.MAX_U32) {
reterr = fmt.Errorf("param index is error. line %v, param %v, index %v", lineNum, key, index)
return
}
nValue, err := strconv.ParseUint(value[0], 10, 32)
if err != nil {
reterr = fmt.Errorf("param value is error. line %v, param %v, value %v", lineNum, key, value)
return
}
writeItem.Uint32SKv[uint32(index)] = uint32(nValue)
case "flag":
index, err := strconv.ParseUint(parts[1], 10, 8)
if err != nil {
reterr = fmt.Errorf("param is error. line %v, param %v", lineNum, key)
return
}
if index == 0 || index > uint64(saasapi.MAX_FLAG) {
reterr = fmt.Errorf("param index is error. line %v, param %v, index %v", lineNum, key, index)
return
}
flag := &saasapi.FlagWithExpire{}
switch strings.ToLower(value[0]) {
case "true":
flag.Flag = true
case "false":
flag.Flag = false
default:
if strings.HasPrefix(value[0], "!") {
// 相对时间戳
nValue, err := strconv.ParseUint(value[0][1:], 10, 32)
if err != nil {
reterr = fmt.Errorf("param value is error. line %v, param %v, value %v", lineNum, key, value)
return
}
flag.Flag = true
flag.Expire = d.currTimeStamp + uint32(nValue)
} else {
nValue, err := strconv.ParseUint(value[0], 10, 32)
if err != nil || nValue > 30*24*86400 {
reterr = fmt.Errorf("param value is error. line %v, param %v, value %v", lineNum, key, value)
return
}
flag.Flag = true
flag.Expire = uint32(nValue)
}
}
writeItem.FlagsWithExpireKv[uint32(index)] = flag
}
}
}
return
}

42
cmd/saastool/exp.go Normal file
View File

@@ -0,0 +1,42 @@
package main
import (
"fmt"
"strings"
)
func RunExp(args ...string) error {
name, args := ParseCommandName(args)
// 从参数中解析出命令
switch name {
case "", "help":
return RunExpHelp(args...)
case "list":
return RunExpList(args...)
case "get":
return RunExpGet(args...)
case "grant":
return RunExpGrant(args...)
default:
return fmt.Errorf(`Unknown command "%s"`+"\n"+`Run 'saastool exp help' for usage`, name)
}
}
func RunExpHelp(args ...string) error {
fmt.Println(strings.TrimSpace(expUsage))
return nil
}
const expUsage = `
Usage: saastool exp COMMAND [OPTIONS]
Commands:
list List exps
get Get exp report
grant Experiment authorization management
"help" is the default command.
Use "saastool exp COMMAND -help" for more information about a command.
`

168
cmd/saastool/exp_get.go Normal file
View File

@@ -0,0 +1,168 @@
package main
import (
"flag"
"fmt"
"net/http"
"slices"
"strconv"
"strings"
"git.algo.com.cn/public/saasapi"
"git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson"
)
type getExpParams struct {
saasHttp *saashttp.SaasClient
bucketIDs []uint32
beginDay uint64
endDay uint64
target string
advertiserIDs []uint64
groupBy []string
totalFlag bool
extFields []string
}
func RunExpGet(args ...string) error {
fs := flag.NewFlagSet("get", flag.ExitOnError)
cfgFile := paramConfig(fs)
beginDay := paramWhereBeginDay(fs)
endDay := paramWhereEndDay(fs)
bucketIDs := paramWhereBucketIds(fs)
target := paramWhereTarget(fs)
advertiserIDs := paramWhereAdvertiserId(fs)
groupBy := paramGroupBy(fs)
totalFlag := paramTotalFlag(fs)
extFields := paramExtFields(fs)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("Command line parse error: %w", err)
}
if fs.NArg() > 0 {
fs.PrintDefaults()
return nil
}
bucketIDsNumSlice := []uint32{}
if *bucketIDs != "" {
expIDsSlice := strings.Split(*bucketIDs, ",")
for _, id := range expIDsSlice {
idNum, err := strconv.ParseUint(id, 10, 32)
if err != nil {
return fmt.Errorf("Expid parse error. value: %v. %w", id, err)
}
if idNum == 0 || idNum > 10 {
return fmt.Errorf("Expid range error.")
}
bucketIDsNumSlice = append(bucketIDsNumSlice, uint32(idNum))
}
}
if *beginDay < 20250101 || *beginDay > 21001231 || *endDay < 20250101 || *endDay > 21001231 {
fs.PrintDefaults()
return fmt.Errorf("Begin/End day error.")
}
if *target == "" {
fs.PrintDefaults()
return fmt.Errorf("Target error.")
}
uidNumSlice := []uint64{}
if *advertiserIDs != "" {
uidSlice := strings.Split(*advertiserIDs, ",")
for _, id := range uidSlice {
idNum, err := strconv.ParseUint(id, 10, 64)
if err != nil {
return fmt.Errorf("Advertiser id parse error. value: %v. %w", id, err)
}
if idNum == 0 {
return fmt.Errorf("Advertiser id error.")
}
uidNumSlice = append(uidNumSlice, idNum)
}
}
groupBySlice := []string{}
if *groupBy != "" {
validGroupBy := map[string]bool{"advertiser_id": true, "user_weight_factor": true}
groupBySlice = strings.Split(*groupBy, ",")
for _, group := range groupBySlice {
if !validGroupBy[group] {
return fmt.Errorf("Group by error. group: %v", group)
}
}
}
extFieldsSlice := []string{}
if *extFields != "" {
extFieldsSlice = strings.Split(*extFields, ",")
if slices.Contains(extFieldsSlice, "") {
return fmt.Errorf("Ext field error.")
}
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
return fmt.Errorf("LoadConfigFile error: %w", err)
}
getExpParams := getExpParams{
saasHttp: &saashttp.SaasClient{
Client: &http.Client{},
ApiUrls: saashttp.InitAPIUrl(&cfg.ApiUrls),
Auth: &cfg.Auth,
},
bucketIDs: bucketIDsNumSlice,
beginDay: *beginDay,
endDay: *endDay,
target: *target,
advertiserIDs: uidNumSlice,
groupBy: groupBySlice,
totalFlag: *totalFlag,
extFields: extFieldsSlice,
}
return doExpGet(getExpParams)
}
func doExpGet(getExpParams getExpParams) error {
totalFlag := uint32(0)
if getExpParams.totalFlag {
totalFlag = 1
}
saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_ExpGet{
ExpGet: &saasapi.ExpGet{
WhereBucketId: getExpParams.bucketIDs,
WhereBeginDay: getExpParams.beginDay,
WhereEndDay: getExpParams.endDay,
WhereTarget: getExpParams.target,
WhereAdvertiserId: getExpParams.advertiserIDs,
GroupBy: getExpParams.groupBy,
TotalFlag: totalFlag,
ExtFields: getExpParams.extFields,
},
},
}
res, err := getExpParams.saasHttp.ExpGet(saasReq)
if err != nil {
return fmt.Errorf("Submit Command error: %w", err)
}
if res.Code != saasapi.ErrorCode_SUCC {
return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
}
getExpRes := res.GetExpGetRes()
fmt.Printf("exp res: %v\n", protojson.Format(getExpRes))
return nil
}

37
cmd/saastool/exp_grant.go Normal file
View File

@@ -0,0 +1,37 @@
package main
import (
"fmt"
"strings"
)
func RunExpGrant(args ...string) error {
name, args := ParseCommandName(args)
switch name {
case "", "help":
fmt.Println(strings.TrimSpace(expGrantUsage))
return nil
case "list":
return RunExpGrantList(args...)
case "add":
return RunExpGrantAdd(args...)
case "delete":
return RunExpGrantDelete(args...)
default:
return fmt.Errorf(`Unknown command "%s"`+"\n"+`Run 'saastool exp grant help' for usage`, name)
}
}
const expGrantUsage = `
Usage: saastool exp grant COMMAND [OPTIONS]
Commands:
list List experiment authorization
add Add experiment authorization
delete Delete experiment authorization
"help" is the default command.
Use "saastool exp grant COMMAND -help" for more information about a command.
`

View File

@@ -0,0 +1,75 @@
package main
import (
"flag"
"fmt"
"net/http"
"git.algo.com.cn/public/saasapi"
"git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson"
)
type expGrantAddParams struct {
srtaAccountId uint32
saasHttp *saashttp.SaasClient
}
func RunExpGrantAdd(args ...string) error {
fs := flag.NewFlagSet("add", flag.ExitOnError)
cfgFile := paramConfig(fs)
srtaAccountId := paramSrtaAccountId(fs)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("Command line parse error: %w", err)
}
if fs.NArg() > 0 {
fs.PrintDefaults()
return nil
}
if *srtaAccountId == 0 {
fs.PrintDefaults()
return fmt.Errorf("sRTA account ID is required")
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
return fmt.Errorf("LoadConfigFile error: %w", err)
}
expGrantAddParams := expGrantAddParams{
srtaAccountId: uint32(*srtaAccountId),
saasHttp: &saashttp.SaasClient{
Client: &http.Client{},
ApiUrls: saashttp.InitAPIUrl(&cfg.ApiUrls),
Auth: &cfg.Auth,
},
}
return doExpGrantAdd(expGrantAddParams)
}
func doExpGrantAdd(params expGrantAddParams) error {
saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_ExpGrantAdd{
ExpGrantAdd: &saasapi.ExpGrant{
TargetAccountId: params.srtaAccountId,
},
},
}
res, err := params.saasHttp.ExpGrantAdd(saasReq)
if err != nil {
return fmt.Errorf("Submit Command error: %w", err)
}
if res.Code != saasapi.ErrorCode_SUCC {
return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
}
expGrantRes := res.GetExpGrantAddRes()
fmt.Printf("exp grant add res: %v\n", protojson.Format(expGrantRes))
return nil
}

View File

@@ -0,0 +1,75 @@
package main
import (
"flag"
"fmt"
"net/http"
"git.algo.com.cn/public/saasapi"
"git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson"
)
type expGrantDeleteParams struct {
srtaAccountId uint32
saasHttp *saashttp.SaasClient
}
func RunExpGrantDelete(args ...string) error {
fs := flag.NewFlagSet("delete", flag.ExitOnError)
cfgFile := paramConfig(fs)
srtaAccountId := paramSrtaAccountId(fs)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("Command line parse error: %w", err)
}
if fs.NArg() > 0 {
fs.PrintDefaults()
return nil
}
if *srtaAccountId == 0 {
fs.PrintDefaults()
return fmt.Errorf("sRTA account ID is required")
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
return fmt.Errorf("LoadConfigFile error: %w", err)
}
expGrantDeleteParams := expGrantDeleteParams{
srtaAccountId: uint32(*srtaAccountId),
saasHttp: &saashttp.SaasClient{
Client: &http.Client{},
ApiUrls: saashttp.InitAPIUrl(&cfg.ApiUrls),
Auth: &cfg.Auth,
},
}
return doExpGrantDelete(expGrantDeleteParams)
}
func doExpGrantDelete(params expGrantDeleteParams) error {
saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_ExpGrantDelete{
ExpGrantDelete: &saasapi.ExpGrant{
TargetAccountId: params.srtaAccountId,
},
},
}
res, err := params.saasHttp.ExpGrantDelete(saasReq)
if err != nil {
return fmt.Errorf("Submit Command error: %w", err)
}
if res.Code != saasapi.ErrorCode_SUCC {
return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
}
expGrantRes := res.GetExpGrantDeleteRes()
fmt.Printf("exp grant delete res: %v\n", protojson.Format(expGrantRes))
return nil
}

View File

@@ -0,0 +1,65 @@
package main
import (
"flag"
"fmt"
"net/http"
"git.algo.com.cn/public/saasapi"
"git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson"
)
type expGrantListParams struct {
saasHttp *saashttp.SaasClient
}
func RunExpGrantList(args ...string) error {
fs := flag.NewFlagSet("list", flag.ExitOnError)
cfgFile := paramConfig(fs)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("Command line parse error: %w", err)
}
if fs.NArg() > 0 {
fs.PrintDefaults()
return nil
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
return fmt.Errorf("LoadConfigFile error: %w", err)
}
expGrantListParams := expGrantListParams{
saasHttp: &saashttp.SaasClient{
Client: &http.Client{},
ApiUrls: saashttp.InitAPIUrl(&cfg.ApiUrls),
Auth: &cfg.Auth,
},
}
return doExpGrantList(expGrantListParams)
}
func doExpGrantList(params expGrantListParams) error {
saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_ExpGrantList{
ExpGrantList: &saasapi.ExpGrantList{},
},
}
res, err := params.saasHttp.ExpGrantList(saasReq)
if err != nil {
return fmt.Errorf("Submit Command error: %w", err)
}
if res.Code != saasapi.ErrorCode_SUCC {
return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
}
expGrantRes := res.GetExpGrantListRes()
fmt.Printf("exp grant list res: %v\n", protojson.Format(expGrantRes))
return nil
}

65
cmd/saastool/exp_list.go Normal file
View File

@@ -0,0 +1,65 @@
package main
import (
"flag"
"fmt"
"net/http"
"git.algo.com.cn/public/saasapi"
"git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson"
)
type listExpParams struct {
saasHttp *saashttp.SaasClient
}
func RunExpList(args ...string) error {
fs := flag.NewFlagSet("list", flag.ExitOnError)
cfgFile := paramConfig(fs)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("Command line parse error: %w", err)
}
if fs.NArg() > 0 {
fs.PrintDefaults()
return nil
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
return fmt.Errorf("LoadConfigFile error: %w", err)
}
listExpParams := listExpParams{
saasHttp: &saashttp.SaasClient{
Client: &http.Client{},
ApiUrls: saashttp.InitAPIUrl(&cfg.ApiUrls),
Auth: &cfg.Auth,
},
}
return doExpList(listExpParams)
}
func doExpList(listExpParams listExpParams) error {
saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_ExpList{
ExpList: &saasapi.ExpList{},
},
}
res, err := listExpParams.saasHttp.ExpList(saasReq)
if err != nil {
return fmt.Errorf("Submit Command error: %w", err)
}
if res.Code != saasapi.ErrorCode_SUCC {
return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
}
listExpRes := res.GetExpListRes()
fmt.Printf("exp res: %v\n", protojson.Format(listExpRes))
return nil
}

42
cmd/saastool/grant.go Normal file
View File

@@ -0,0 +1,42 @@
package main
import (
"fmt"
"strings"
)
func RunGrant(args ...string) error {
name, args := ParseCommandName(args)
// 从参数中解析出命令
switch name {
case "", "help":
return RunGrantHelp(args...)
case "list":
return RunGrantList(args...)
case "add":
return RunGrantAdd(args...)
case "delete":
return RunGrantDelete(args...)
default:
return fmt.Errorf(`Unknown command "%s"`+"\n"+`Run 'saastool grant help' for usage`, name)
}
}
func RunGrantHelp(args ...string) error {
fmt.Println(strings.TrimSpace(grantUsage))
return nil
}
const grantUsage = `
Usage: saastool grant COMMAND [OPTIONS]
Commands:
list List data grants
add Add data grant
delete Delete data grant
"help" is the default command.
Use "saastool grant COMMAND -help" for more information about a command.
`

93
cmd/saastool/grant_add.go Normal file
View File

@@ -0,0 +1,93 @@
package main
import (
"flag"
"fmt"
"net/http"
"git.algo.com.cn/public/saasapi"
"git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson"
)
type grantAddParams struct {
srtaAccountId uint32
grantIndex string
ds uint32
saasHttp *saashttp.SaasClient
}
func RunGrantAdd(args ...string) error {
fs := flag.NewFlagSet("add", flag.ExitOnError)
cfgFile := paramConfig(fs)
srtaAccountId := paramSrtaAccountId(fs)
dsid := paramRawDataSpaceId(fs)
grantIndex := paramGrantIndex(fs)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("Command line parse error: %w", err)
}
if fs.NArg() > 0 {
fs.PrintDefaults()
return nil
}
if *srtaAccountId == 0 {
fs.PrintDefaults()
return fmt.Errorf("sRTA account ID is required.")
}
if *grantIndex == "" {
fs.PrintDefaults()
return fmt.Errorf("Grant index is required.")
}
if *dsid == 0 {
fs.PrintDefaults()
return fmt.Errorf("Data space ID is required.")
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
return fmt.Errorf("LoadConfigFile error: %w", err)
}
grantAddParams := grantAddParams{
srtaAccountId: uint32(*srtaAccountId),
grantIndex: *grantIndex,
ds: uint32(*dsid),
saasHttp: &saashttp.SaasClient{
Client: &http.Client{},
ApiUrls: saashttp.InitAPIUrl(&cfg.ApiUrls),
Auth: &cfg.Auth,
},
}
return doGrantAdd(grantAddParams)
}
func doGrantAdd(params grantAddParams) error {
saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_GrantAdd{
GrantAdd: &saasapi.Grant{
TargetAccountId: params.srtaAccountId,
GrantIndex: params.grantIndex,
DataspaceId: params.ds,
},
},
}
res, err := params.saasHttp.GrantAdd(saasReq)
if err != nil {
return fmt.Errorf("Submit Command error: %w", err)
}
if res.Code != saasapi.ErrorCode_SUCC {
return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
}
grantRes := res.GetGrantAddRes()
fmt.Printf("grant add res: %v\n", protojson.Format(grantRes))
return nil
}

View File

@@ -0,0 +1,93 @@
package main
import (
"flag"
"fmt"
"net/http"
"git.algo.com.cn/public/saasapi"
"git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson"
)
type grantDeleteParams struct {
srtaAccountId uint32
grantIndex string
ds uint32
saasHttp *saashttp.SaasClient
}
func RunGrantDelete(args ...string) error {
fs := flag.NewFlagSet("delete", flag.ExitOnError)
cfgFile := paramConfig(fs)
dsid := paramRawDataSpaceId(fs)
srtaAccountId := paramSrtaAccountId(fs)
grantIndex := paramGrantIndex(fs)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("Command line parse error: %w", err)
}
if fs.NArg() > 0 {
fs.PrintDefaults()
return nil
}
if *dsid == 0 {
fs.PrintDefaults()
return fmt.Errorf("data space ID is required.")
}
if *srtaAccountId == 0 {
fs.PrintDefaults()
return fmt.Errorf("sRTA account ID is required.")
}
if *grantIndex == "" {
fs.PrintDefaults()
return fmt.Errorf("grant index is required.")
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
return fmt.Errorf("LoadConfigFile error: %w", err)
}
grantDeleteParams := grantDeleteParams{
srtaAccountId: uint32(*srtaAccountId),
grantIndex: *grantIndex,
ds: uint32(*dsid),
saasHttp: &saashttp.SaasClient{
Client: &http.Client{},
ApiUrls: saashttp.InitAPIUrl(&cfg.ApiUrls),
Auth: &cfg.Auth,
},
}
return doGrantDelete(grantDeleteParams)
}
func doGrantDelete(params grantDeleteParams) error {
saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_GrantDelete{
GrantDelete: &saasapi.Grant{
TargetAccountId: params.srtaAccountId,
GrantIndex: params.grantIndex,
DataspaceId: params.ds,
},
},
}
res, err := params.saasHttp.GrantDelete(saasReq)
if err != nil {
return fmt.Errorf("Submit Command error: %w", err)
}
if res.Code != saasapi.ErrorCode_SUCC {
return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
}
grantRes := res.GetGrantDeleteRes()
fmt.Printf("grant delete res: %v\n", protojson.Format(grantRes))
return nil
}

View File

@@ -0,0 +1,65 @@
package main
import (
"flag"
"fmt"
"net/http"
"git.algo.com.cn/public/saasapi"
"git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson"
)
type grantListParams struct {
saasHttp *saashttp.SaasClient
}
func RunGrantList(args ...string) error {
fs := flag.NewFlagSet("list", flag.ExitOnError)
cfgFile := paramConfig(fs)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("Command line parse error: %w", err)
}
if fs.NArg() > 0 {
fs.PrintDefaults()
return nil
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
return fmt.Errorf("LoadConfigFile error: %w", err)
}
grantListParams := grantListParams{
saasHttp: &saashttp.SaasClient{
Client: &http.Client{},
ApiUrls: saashttp.InitAPIUrl(&cfg.ApiUrls),
Auth: &cfg.Auth,
},
}
return doGrantList(grantListParams)
}
func doGrantList(params grantListParams) error {
saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_GrantList{
GrantList: &saasapi.GrantList{},
},
}
res, err := params.saasHttp.GrantList(saasReq)
if err != nil {
return fmt.Errorf("Submit Command error: %w", err)
}
if res.Code != saasapi.ErrorCode_SUCC {
return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
}
grantRes := res.GetGrantListRes()
fmt.Printf("grant list res: %v\n", protojson.Format(grantRes))
return nil
}

View File

@@ -19,12 +19,18 @@ Commands:
write Write user's 'bytes / uint32s / flags' write Write user's 'bytes / uint32s / flags'
read Read user's 'bytes / uint32s / flags' read Read user's 'bytes / uint32s / flags'
columnwrite Write columns for 'deviceid / openid' users columnwrite Write columns for 'deviceid / openid' users
resetds Reset data space
convert Convert data to write format convert Convert data to write format
task Task commands task Task commands
target Target commands target Target commands
bind Bind commands bind Bind commands
grant Grant commands
script Script commands
exp Exp commands
daemon Run in daemon mode
"help" is the default command. "help" is the default command.

View File

@@ -4,10 +4,9 @@ import (
"flag" "flag"
"fmt" "fmt"
"net/http" "net/http"
"os"
"e.coding.net/rta/public/saasapi" "git.algo.com.cn/public/saasapi"
"e.coding.net/rta/public/saasapi/pkg/saashttp" "git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/protojson"
) )
@@ -20,8 +19,7 @@ func RunInfo(args ...string) error {
cfgFile := paramConfig(fs) cfgFile := paramConfig(fs)
if err := fs.Parse(args); err != nil { if err := fs.Parse(args); err != nil {
fmt.Fprintln(os.Stderr, "command line parse error", "err", err) return fmt.Errorf("Command line parse error: %w", err)
return err
} }
if fs.NArg() > 0 { if fs.NArg() > 0 {
@@ -31,8 +29,7 @@ func RunInfo(args ...string) error {
cfg, err := LoadConfigFile(*cfgFile) cfg, err := LoadConfigFile(*cfgFile)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "LoadConfigFile error", "err", err) return fmt.Errorf("LoadConfigFile error: %w", err)
return err
} }
infoParams := infoParams{ infoParams := infoParams{
@@ -53,19 +50,16 @@ func doInfo(infoParams infoParams) error {
} }
res, err := infoParams.saasHttp.Info(saasReq) res, err := infoParams.saasHttp.Info(saasReq)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "submit Info error", "err", err) return fmt.Errorf("Submit Command error: %w", err)
return err
} }
if res.Code != saasapi.ErrorCode_SUCC { if res.Code != saasapi.ErrorCode_SUCC {
fmt.Fprintln(os.Stderr, "info failed", "code", res.Code, "status", res.Status) return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
return nil
} }
infoRes := res.GetInfoRes() infoRes := res.GetInfoRes()
fmt.Printf("info res: %v\n", protojson.Format(infoRes)) fmt.Printf("Info res: %v\n", protojson.Format(infoRes))
return nil return nil
} }

View File

@@ -7,6 +7,7 @@ import (
func main() { func main() {
if err := Run(os.Args[1:]...); err != nil { if err := Run(os.Args[1:]...); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1) os.Exit(1)
} }
} }
@@ -26,6 +27,8 @@ func Run(args ...string) error {
return RunRead(args...) return RunRead(args...)
case "columnwrite": case "columnwrite":
return RunColumnWrite(args...) return RunColumnWrite(args...)
case "resetds":
return RunResetDs(args...)
case "convert": case "convert":
return RunConvert(args...) return RunConvert(args...)
case "verify": case "verify":
@@ -36,9 +39,15 @@ func Run(args ...string) error {
return RunTarget(args...) return RunTarget(args...)
case "bind": case "bind":
return RunBind(args...) return RunBind(args...)
case "grant":
return RunGrant(args...)
case "script":
return RunScript(args...)
case "exp":
return RunExp(args...)
case "daemon":
return RunDaemon(args...)
default: default:
err := fmt.Errorf(`unknown command "%v"`+"\n"+`Run 'saastool help' for usage`, name) return fmt.Errorf(`Unknown command "%v"`+"\n"+`Run 'saastool help' for usage`, name)
fmt.Fprintln(os.Stderr, err.Error())
return err
} }
} }

View File

@@ -105,6 +105,66 @@ func paramIDs(fs *flag.FlagSet) *string {
return fs.String("ids", "", "IDs for delete. Use commas to separate multiple IDs") return fs.String("ids", "", "IDs for delete. Use commas to separate multiple IDs")
} }
func paramLua(fs *flag.FlagSet) *string {
return fs.String("lua", "", "LUA file name")
}
func paramName(fs *flag.FlagSet) *string {
return fs.String("name", "", "Name")
}
func paramDid(fs *flag.FlagSet) *string {
return fs.String("did", "", "device md5 (lower case)")
}
func paramOS(fs *flag.FlagSet) *uint {
return fs.Uint("os", 2, "1=iOS, 2=Android, 7=Harmony default=2")
}
func paramWhereBeginDay(fs *flag.FlagSet) *uint64 {
return fs.Uint64("beginday", 0, "Begin day")
}
func paramWhereEndDay(fs *flag.FlagSet) *uint64 {
return fs.Uint64("endday", 0, "End day")
}
func paramWhereBucketIds(fs *flag.FlagSet) *string {
return fs.String("bucketids", "", "Bucket IDs. Use commas to separate multiple IDs. empty is all")
}
func paramWhereTarget(fs *flag.FlagSet) *string {
return fs.String("target", "", "Target ID")
}
func paramWhereAdvertiserId(fs *flag.FlagSet) *string {
return fs.String("uid", "", "Advertiser IDs. Use commas to separate multiple IDs.")
}
func paramGroupBy(fs *flag.FlagSet) *string {
return fs.String("groupby", "", "Group by. Use commas to separate multiple fields. empty is none")
}
func paramExtFields(fs *flag.FlagSet) *string {
return fs.String("extfields", "", "Ext fields. Use commas to separate multiple fields. * is all")
}
func paramTotalFlag(fs *flag.FlagSet) *bool {
return fs.Bool("total", false, "Total flag")
}
func paramSrtaAccountId(fs *flag.FlagSet) *uint64 {
return fs.Uint64("account", 0, "sRTA account ID")
}
func paramRawDataSpaceId(fs *flag.FlagSet) *uint64 {
return fs.Uint64("ds", 0, "Raw data space ID")
}
func paramGrantIndex(fs *flag.FlagSet) *string {
return fs.String("index", "", "Grant index. Format: \"1, 2, 4, 55-64\"")
}
// ParseByteSize 解析字节大小字符串为字节数 // ParseByteSize 解析字节大小字符串为字节数
func ParseByteSize(sizeStr string) (uint64, error) { func ParseByteSize(sizeStr string) (uint64, error) {
sizeStr = strings.TrimSpace(sizeStr) sizeStr = strings.TrimSpace(sizeStr)

View File

@@ -4,11 +4,10 @@ import (
"flag" "flag"
"fmt" "fmt"
"net/http" "net/http"
"os"
"strings" "strings"
"e.coding.net/rta/public/saasapi" "git.algo.com.cn/public/saasapi"
"e.coding.net/rta/public/saasapi/pkg/saashttp" "git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/protojson"
) )
@@ -32,8 +31,7 @@ func RunRead(args ...string) error {
userids := paramUserids(fs) userids := paramUserids(fs)
if err := fs.Parse(args); err != nil { if err := fs.Parse(args); err != nil {
fmt.Fprintln(os.Stderr, "command line parse error", "err", err) return fmt.Errorf("Command line parse error: %w", err)
return err
} }
// 切割字符串 // 切割字符串
@@ -44,15 +42,13 @@ func RunRead(args ...string) error {
return nil return nil
} }
if strings.ToLower(*ds) == "openid" && len(*appid) == 0 { if strings.ToLower(*ds) == "wuid" && len(*appid) == 0 {
fmt.Fprintln(os.Stderr, "appid must be set when data space is openid") return fmt.Errorf("Appid must be set when data space is wuid.")
return nil
} }
cfg, err := LoadConfigFile(*cfgFile) cfg, err := LoadConfigFile(*cfgFile)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "load config file error", "err", err) return fmt.Errorf("LoadConfigFile error: %w", err)
return err
} }
readParams := readParams{ readParams := readParams{
@@ -92,18 +88,16 @@ func doRead(readParams readParams) error {
read.ReadItems = saasReadItems read.ReadItems = saasReadItems
res, err := readParams.saasHttp.Read(saasReq) res, err := readParams.saasHttp.Read(saasReq)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "submit read error", "err", err) return fmt.Errorf("Submit Command error: %w", err)
return err
} }
if res.GetCode() != saasapi.ErrorCode_SUCC { if res.GetCode() != saasapi.ErrorCode_SUCC {
fmt.Fprintln(os.Stderr, protojson.Format(res)) return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
return err
} else {
fmt.Println(protojson.Format(res))
} }
readRes := res.GetReadRes()
fmt.Printf("read res: %v\n", protojson.Format(readRes))
return nil return nil
} }

71
cmd/saastool/resetds.go Normal file
View File

@@ -0,0 +1,71 @@
package main
import (
"flag"
"fmt"
"net/http"
"git.algo.com.cn/public/saasapi"
"git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson"
)
type resetDsParams struct {
ds string
saasHttp *saashttp.SaasClient
}
func RunResetDs(args ...string) error {
fs := flag.NewFlagSet("resetds", flag.ExitOnError)
cfgFile := paramConfig(fs)
ds := paramDataSpaceId(fs)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("Command line parse error: %w", err)
}
if fs.NArg() > 0 || len(*ds) == 0 {
fs.PrintDefaults()
return nil
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
return fmt.Errorf("LoadConfigFile error: %w", err)
}
resetDsParams := resetDsParams{
ds: *ds,
saasHttp: &saashttp.SaasClient{
Client: &http.Client{},
ApiUrls: saashttp.InitAPIUrl(&cfg.ApiUrls),
Auth: &cfg.Auth,
},
}
return doResetDs(resetDsParams)
}
func doResetDs(resetDsParams resetDsParams) error {
saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_ResetDs{
ResetDs: &saasapi.ResetDs{
DataspaceId: resetDsParams.ds,
},
},
}
res, err := resetDsParams.saasHttp.ResetDS(saasReq)
if err != nil {
return fmt.Errorf("Submit Command error: %w", err)
}
if res.Code != saasapi.ErrorCode_SUCC {
return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
}
resetRes := res.GetResetDsRes()
fmt.Printf("ResetDS res: %v\n", protojson.Format(resetRes))
return nil
}

51
cmd/saastool/script.go Normal file
View File

@@ -0,0 +1,51 @@
package main
import (
"fmt"
"strings"
)
func RunScript(args ...string) error {
name, args := ParseCommandName(args)
// 从参数中解析出命令
switch name {
case "", "help":
return RunScriptHelp(args...)
case "debug", "run":
return RunScriptDebug(args...)
case "create":
return RunScriptCreate(args...)
case "list":
return RunScriptList(args...)
case "delete":
return RunScriptDelete(args...)
case "get":
return RunScriptGet(args...)
case "use":
return RunScriptUse(args...)
default:
return fmt.Errorf(`Unknown command "%s"`+"\n"+`Run 'saastool script help' for usage`, name)
}
}
func RunScriptHelp(args ...string) error {
fmt.Println(strings.TrimSpace(scriptUsage))
return nil
}
const scriptUsage = `
Usage: saastool script COMMAND [OPTIONS]
Commands:
debug Debug lua script on server
create Create lua script on server
list List all scripts on server
delete Delete a script from server
get Get script content from server
use Use a script as default
"help" is the default command.
Use "saastool script COMMAND -help" for more information about a command.
`

View File

@@ -0,0 +1,88 @@
package main
import (
"flag"
"fmt"
"io"
"net/http"
"os"
"git.algo.com.cn/public/saasapi"
"git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson"
)
type scriptCreateParams struct {
luaName string
luaScript string
saasHttp *saashttp.SaasClient
}
func RunScriptCreate(args ...string) error {
fs := flag.NewFlagSet("create", flag.ExitOnError)
cfgFile := paramConfig(fs)
luaFile := paramLua(fs)
luaName := paramName(fs)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("Command line parse error: %w", err)
}
if fs.NArg() > 0 || len(*luaFile) == 0 || len(*luaName) == 0 {
fs.PrintDefaults()
return nil
}
file, err := os.Open(*luaFile)
if err != nil {
return fmt.Errorf("Lua file open error: %w", err)
}
defer file.Close()
body, err := io.ReadAll(file)
if err != nil {
return fmt.Errorf("Lua file read error: %w", err)
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
return fmt.Errorf("LoadConfigFile error: %w", err)
}
scriptCreateParams := scriptCreateParams{
luaName: *luaName,
luaScript: string(body),
saasHttp: &saashttp.SaasClient{
Client: &http.Client{},
ApiUrls: saashttp.InitAPIUrl(&cfg.ApiUrls),
Auth: &cfg.Auth,
},
}
return doScriptCreate(scriptCreateParams)
}
func doScriptCreate(scriptCreateParams scriptCreateParams) error {
saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_ScriptCreate{
ScriptCreate: &saasapi.ScriptCreate{
LuaName: scriptCreateParams.luaName,
LuaScript: scriptCreateParams.luaScript,
},
},
}
res, err := scriptCreateParams.saasHttp.ScriptCreate(saasReq)
if err != nil {
return fmt.Errorf("Submit Command error: %w", err)
}
if res.Code != saasapi.ErrorCode_SUCC {
return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
}
scriptRes := res.GetScriptCreateRes()
fmt.Printf("script res: %v\n", protojson.Format(scriptRes))
return nil
}

View File

@@ -0,0 +1,105 @@
package main
import (
"flag"
"fmt"
"io"
"net/http"
"os"
"git.algo.com.cn/public/saasapi"
"git.algo.com.cn/public/saasapi/pkg/saashttp"
)
type scriptDebugParams struct {
luaScript string
did string
os saasapi.OS
saasHttp *saashttp.SaasClient
}
func RunScriptDebug(args ...string) error {
fs := flag.NewFlagSet("debug", flag.ExitOnError)
cfgFile := paramConfig(fs)
luaFile := paramLua(fs)
did := paramDid(fs)
tos := paramOS(fs)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("Command line parse error: %w", err)
}
if fs.NArg() > 0 || len(*luaFile) == 0 || len(*did) == 0 {
fs.PrintDefaults()
return nil
}
if !(*tos == 1 || *tos == 2 || *tos == 7) {
fs.PrintDefaults()
return nil
}
file, err := os.Open(*luaFile)
if err != nil {
return fmt.Errorf("Lua file open error: %w", err)
}
defer file.Close()
body, err := io.ReadAll(file)
if err != nil {
return fmt.Errorf("Lua file read error: %w", err)
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
return fmt.Errorf("LoadConfigFile error: %w", err)
}
scriptDebugParams := scriptDebugParams{
luaScript: string(body),
did: *did,
os: saasapi.OS(*tos),
saasHttp: &saashttp.SaasClient{
Client: &http.Client{},
ApiUrls: saashttp.InitAPIUrl(&cfg.ApiUrls),
Auth: &cfg.Auth,
},
}
return doScriptDebug(scriptDebugParams)
}
func doScriptDebug(scriptDebugParams scriptDebugParams) error {
saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_ScriptDebug{
ScriptDebug: &saasapi.ScriptDebug{
LuaScript: scriptDebugParams.luaScript,
ServerDid: scriptDebugParams.did,
Os: scriptDebugParams.os,
},
},
}
res, err := scriptDebugParams.saasHttp.ScriptDebug(saasReq)
if err != nil {
return fmt.Errorf("Submit Command error: %w", err)
}
if res.Code != saasapi.ErrorCode_SUCC {
return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
}
scriptDebugRes := res.GetScriptDebugRes()
fmt.Println("ERROROUT_OUTPUT:")
fmt.Print(scriptDebugRes.GetErrorOutput())
fmt.Println()
fmt.Println("PRINT_OUTPUT:")
fmt.Print(scriptDebugRes.GetPrintOutput())
fmt.Println()
fmt.Println("DATASPACE_OUTPUT:")
fmt.Print(scriptDebugRes.GetDataspaceOut())
fmt.Println()
fmt.Println("TARGETS_OUTPUT:")
fmt.Print(scriptDebugRes.GetTargetsOutput())
return nil
}

View File

@@ -0,0 +1,71 @@
package main
import (
"flag"
"fmt"
"net/http"
"git.algo.com.cn/public/saasapi"
"git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson"
)
type scriptDeleteParams struct {
luaName string
saasHttp *saashttp.SaasClient
}
func RunScriptDelete(args ...string) error {
fs := flag.NewFlagSet("delete", flag.ExitOnError)
cfgFile := paramConfig(fs)
luaName := paramName(fs)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("Command line parse error: %w", err)
}
if fs.NArg() > 0 || len(*luaName) == 0 {
fs.PrintDefaults()
return nil
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
return fmt.Errorf("LoadConfigFile error: %w", err)
}
scriptDeleteParams := scriptDeleteParams{
luaName: *luaName,
saasHttp: &saashttp.SaasClient{
Client: &http.Client{},
ApiUrls: saashttp.InitAPIUrl(&cfg.ApiUrls),
Auth: &cfg.Auth,
},
}
return doScriptDelete(scriptDeleteParams)
}
func doScriptDelete(scriptDeleteParams scriptDeleteParams) error {
saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_ScriptDelete{
ScriptDelete: &saasapi.ScriptDelete{
LuaName: scriptDeleteParams.luaName,
},
},
}
res, err := scriptDeleteParams.saasHttp.ScriptDelete(saasReq)
if err != nil {
return fmt.Errorf("Submit Command error: %w", err)
}
if res.Code != saasapi.ErrorCode_SUCC {
return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
}
scriptRes := res.GetScriptDeleteRes()
fmt.Printf("script res: %v\n", protojson.Format(scriptRes))
return nil
}

View File

@@ -0,0 +1,71 @@
package main
import (
"flag"
"fmt"
"net/http"
"git.algo.com.cn/public/saasapi"
"git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson"
)
type scriptGetParams struct {
luaName string
saasHttp *saashttp.SaasClient
}
func RunScriptGet(args ...string) error {
fs := flag.NewFlagSet("get", flag.ExitOnError)
cfgFile := paramConfig(fs)
luaName := paramName(fs)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("Command line parse error: %w", err)
}
if fs.NArg() > 0 || len(*luaName) == 0 {
fs.PrintDefaults()
return nil
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
return fmt.Errorf("LoadConfigFile error: %w", err)
}
scriptGetParams := scriptGetParams{
luaName: *luaName,
saasHttp: &saashttp.SaasClient{
Client: &http.Client{},
ApiUrls: saashttp.InitAPIUrl(&cfg.ApiUrls),
Auth: &cfg.Auth,
},
}
return doScriptGet(scriptGetParams)
}
func doScriptGet(scriptGetParams scriptGetParams) error {
saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_ScriptGet{
ScriptGet: &saasapi.ScriptGet{
LuaName: scriptGetParams.luaName,
},
},
}
res, err := scriptGetParams.saasHttp.ScriptGet(saasReq)
if err != nil {
return fmt.Errorf("Submit Command error: %w", err)
}
if res.Code != saasapi.ErrorCode_SUCC {
return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
}
scriptRes := res.GetScriptGetRes()
fmt.Printf("script res: %v\n", protojson.Format(scriptRes))
return nil
}

View File

@@ -0,0 +1,66 @@
package main
import (
"flag"
"fmt"
"net/http"
"git.algo.com.cn/public/saasapi"
"git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson"
)
type scriptListParams struct {
saasHttp *saashttp.SaasClient
}
func RunScriptList(args ...string) error {
fs := flag.NewFlagSet("list", flag.ExitOnError)
cfgFile := paramConfig(fs)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("Command line parse error: %w", err)
}
if fs.NArg() > 0 {
fs.PrintDefaults()
return nil
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
return fmt.Errorf("LoadConfigFile error: %w", err)
}
scriptListParams := scriptListParams{
saasHttp: &saashttp.SaasClient{
Client: &http.Client{},
ApiUrls: saashttp.InitAPIUrl(&cfg.ApiUrls),
Auth: &cfg.Auth,
},
}
return doScriptList(scriptListParams)
}
func doScriptList(scriptListParams scriptListParams) error {
saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_ScriptList{
ScriptList: &saasapi.ScriptList{},
},
}
res, err := scriptListParams.saasHttp.ScriptList(saasReq)
if err != nil {
return fmt.Errorf("Submit Command error: %w", err)
}
if res.Code != saasapi.ErrorCode_SUCC {
return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
}
scriptRes := res.GetScriptListRes()
fmt.Printf("script res: %v\n", protojson.Format(scriptRes))
return nil
}

View File

@@ -0,0 +1,71 @@
package main
import (
"flag"
"fmt"
"net/http"
"git.algo.com.cn/public/saasapi"
"git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson"
)
type scriptUseParams struct {
luaName string
saasHttp *saashttp.SaasClient
}
func RunScriptUse(args ...string) error {
fs := flag.NewFlagSet("use", flag.ExitOnError)
cfgFile := paramConfig(fs)
luaName := paramName(fs)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("Command line parse error: %w", err)
}
if fs.NArg() > 0 || len(*luaName) == 0 {
fs.PrintDefaults()
return nil
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
return fmt.Errorf("LoadConfigFile error: %w", err)
}
scriptUseParams := scriptUseParams{
luaName: *luaName,
saasHttp: &saashttp.SaasClient{
Client: &http.Client{},
ApiUrls: saashttp.InitAPIUrl(&cfg.ApiUrls),
Auth: &cfg.Auth,
},
}
return doScriptUse(scriptUseParams)
}
func doScriptUse(scriptUseParams scriptUseParams) error {
saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_ScriptUse{
ScriptUse: &saasapi.ScriptUse{
LuaName: scriptUseParams.luaName,
},
},
}
res, err := scriptUseParams.saasHttp.ScriptUse(saasReq)
if err != nil {
return fmt.Errorf("Submit Command error: %w", err)
}
if res.Code != saasapi.ErrorCode_SUCC {
return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
}
scriptRes := res.GetScriptUseRes()
fmt.Printf("script use res: %v\n", protojson.Format(scriptRes))
return nil
}

View File

@@ -2,7 +2,6 @@ package main
import ( import (
"fmt" "fmt"
"os"
"strings" "strings"
) )
@@ -15,11 +14,12 @@ func RunTarget(args ...string) error {
return RunTargetHelp(args...) return RunTargetHelp(args...)
case "list": case "list":
return RunTargetList(args...) return RunTargetList(args...)
case "create":
return RunTargetCreate(args...)
case "delete":
return RunTargetDelete(args...)
default: default:
err := fmt.Errorf(`unknown command "%s"`+"\n"+`Run 'saastool target help' for usage`, name) return fmt.Errorf(`Unknown command "%s"`+"\n"+`Run 'saastool target help' for usage`, name)
fmt.Fprintln(os.Stderr, err)
return err
} }
} }
@@ -33,6 +33,8 @@ Usage: saastoola target COMMAND [OPTIONS]
Commands: Commands:
list List targets list List targets
create Create a new target
delete Delete an existing target
"help" is the default command. "help" is the default command.

View File

@@ -1,38 +0,0 @@
package main
import (
"encoding/json"
"os"
)
// MapConfig 配置
type MapConfig struct {
Targets map[string]*Target `json:"targets"`
}
// Target 配置
type Target struct {
WriteByte *byte `json:"write_byte"` // byte值
WriteBytePos int `json:"write_byte_pos"` // byte写入位置
WriteUint32 *uint32 `json:"write_uint32"` // uint32值
WriteUint32Pos int `json:"write_uint32_pos"` // uint32写入位置
WriteFlag *bool `json:"write_flag"` // 标志位
WriteExpire *uint32 `json:"write_expire"` // 过期时间
WriteFlagWithExpirePos int `json:"write_flag_with_expire_pos"` // 标志与过期写入位置
}
// LoadConfigFile 加载配置文件
func LoadMapFile(filename string) (*MapConfig, error) {
// 打开文件
f, err := os.Open(filename)
if err != nil {
return nil, err
}
defer f.Close()
sc := &MapConfig{}
err = json.NewDecoder(f).Decode(sc)
return sc, err
}

View File

@@ -0,0 +1,75 @@
package main
import (
"flag"
"fmt"
"net/http"
"git.algo.com.cn/public/saasapi"
"git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson"
)
type createTargetParams struct {
targetId string
targetDesc string
saasHttp *saashttp.SaasClient
}
func RunTargetCreate(args ...string) error {
fs := flag.NewFlagSet("create", flag.ExitOnError)
cfgFile := paramConfig(fs)
targetId := paramTarget(fs)
targetDesc := paramTaskDesc(fs)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("Command line parse error: %w", err)
}
if fs.NArg() > 0 || len(*targetId) == 0 {
fs.PrintDefaults()
return nil
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
return fmt.Errorf("LoadConfigFile error: %w", err)
}
createTargetParams := createTargetParams{
targetId: *targetId,
targetDesc: *targetDesc,
saasHttp: &saashttp.SaasClient{
Client: &http.Client{},
ApiUrls: saashttp.InitAPIUrl(&cfg.ApiUrls),
Auth: &cfg.Auth,
},
}
return doTargetCreate(createTargetParams)
}
func doTargetCreate(createTargetParams createTargetParams) error {
saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_TargetCreate{
TargetCreate: &saasapi.TargetCreate{
TargetId: createTargetParams.targetId,
TargetDescription: createTargetParams.targetDesc,
},
},
}
res, err := createTargetParams.saasHttp.TargetCreate(saasReq)
if err != nil {
return fmt.Errorf("Submit Command error: %w", err)
}
if res.Code != saasapi.ErrorCode_SUCC {
return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
}
targetRes := res.GetTargetCreateRes()
fmt.Printf("target res: %v\n", protojson.Format(targetRes))
return nil
}

View File

@@ -0,0 +1,70 @@
package main
import (
"flag"
"fmt"
"net/http"
"git.algo.com.cn/public/saasapi"
"git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson"
)
type deleteTargetParams struct {
targetId string
saasHttp *saashttp.SaasClient
}
func RunTargetDelete(args ...string) error {
fs := flag.NewFlagSet("delete", flag.ExitOnError)
cfgFile := paramConfig(fs)
targetId := paramTarget(fs)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("Command line parse error: %w", err)
}
if fs.NArg() > 0 || len(*targetId) == 0 {
fs.PrintDefaults()
return nil
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
return fmt.Errorf("LoadConfigFile error: %w", err)
}
deleteTargetParams := deleteTargetParams{
targetId: *targetId,
saasHttp: &saashttp.SaasClient{
Client: &http.Client{},
ApiUrls: saashttp.InitAPIUrl(&cfg.ApiUrls),
Auth: &cfg.Auth,
},
}
return doTargetDelete(deleteTargetParams)
}
func doTargetDelete(deleteTargetParams deleteTargetParams) error {
saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_TargetDelete{
TargetDelete: &saasapi.TargetDelete{
TargetId: deleteTargetParams.targetId,
},
},
}
res, err := deleteTargetParams.saasHttp.TargetDelete(saasReq)
if err != nil {
return fmt.Errorf("Submit Command error: %w", err)
}
if res.Code != saasapi.ErrorCode_SUCC {
return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
}
targetDeleteRes := res.GetTargetDeleteRes()
fmt.Printf("target res: %v\n", protojson.Format(targetDeleteRes))
return nil
}

View File

@@ -4,11 +4,10 @@ import (
"flag" "flag"
"fmt" "fmt"
"net/http" "net/http"
"os"
"strings" "strings"
"e.coding.net/rta/public/saasapi" "git.algo.com.cn/public/saasapi"
"e.coding.net/rta/public/saasapi/pkg/saashttp" "git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/protojson"
) )
@@ -25,8 +24,7 @@ func RunTargetList(args ...string) error {
listBinds := paramListBinds(fs) listBinds := paramListBinds(fs)
if err := fs.Parse(args); err != nil { if err := fs.Parse(args); err != nil {
fmt.Fprintln(os.Stderr, "command line parse error", "err", err) return fmt.Errorf("Command line parse error: %w", err)
return err
} }
if fs.NArg() > 0 { if fs.NArg() > 0 {
@@ -42,8 +40,7 @@ func RunTargetList(args ...string) error {
cfg, err := LoadConfigFile(*cfgFile) cfg, err := LoadConfigFile(*cfgFile)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "LoadConfigFile error", "err", err) return fmt.Errorf("LoadConfigFile error: %w", err)
return err
} }
listTargetParams := listTargetParams{ listTargetParams := listTargetParams{
@@ -70,15 +67,12 @@ func doTargetList(listTargetParams listTargetParams) error {
} }
res, err := listTargetParams.saasHttp.TargetList(saasReq) res, err := listTargetParams.saasHttp.TargetList(saasReq)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "submit List Target error", "err", err) return fmt.Errorf("Submit Command error: %w", err)
return err
} }
if res.Code != saasapi.ErrorCode_SUCC { if res.Code != saasapi.ErrorCode_SUCC {
fmt.Fprintln(os.Stderr, "Target list failed", "code", res.Code, "status", res.Status) return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
return nil
} }
targetRes := res.GetTargetListRes() targetRes := res.GetTargetListRes()

View File

@@ -2,7 +2,6 @@ package main
import ( import (
"fmt" "fmt"
"os"
"strings" "strings"
) )
@@ -30,10 +29,7 @@ func RunTask(args ...string) error {
case "run": case "run":
return RunTaskRun(args...) return RunTaskRun(args...)
default: default:
err := fmt.Errorf(`unknown command "%s"`+"\n"+`Run 'saastool task help' for usage`, name) return fmt.Errorf(`Unknown command "%s"`+"\n"+`Run 'saastool task help' for usage`, name)
fmt.Fprintln(os.Stderr, err)
return err
} }
} }

View File

@@ -6,8 +6,8 @@ import (
"net/http" "net/http"
"os" "os"
"e.coding.net/rta/public/saasapi" "git.algo.com.cn/public/saasapi"
"e.coding.net/rta/public/saasapi/pkg/saashttp" "git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/protojson"
) )
@@ -23,8 +23,7 @@ func RunTaskCreate(args ...string) error {
hashFile := paramInputHashFile(fs) hashFile := paramInputHashFile(fs)
if err := fs.Parse(args); err != nil { if err := fs.Parse(args); err != nil {
fmt.Fprintln(os.Stderr, "command line parse error", "err", err) return fmt.Errorf("Command line parse error: %w", err)
return err
} }
if fs.NArg() > 0 || len(*hashFile) == 0 { if fs.NArg() > 0 || len(*hashFile) == 0 {
@@ -34,8 +33,7 @@ func RunTaskCreate(args ...string) error {
cfg, err := LoadConfigFile(*cfgFile) cfg, err := LoadConfigFile(*cfgFile)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "LoadConfigFile error", "err", err) return fmt.Errorf("LoadConfigFile error: %w", err)
return err
} }
createTaskParams := createTaskParams{ createTaskParams := createTaskParams{
@@ -50,12 +48,11 @@ func RunTaskCreate(args ...string) error {
taskBuf, err := os.ReadFile(createTaskParams.hashFile) taskBuf, err := os.ReadFile(createTaskParams.hashFile)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "open task file error", "err", err) return fmt.Errorf("open task file error: %w", err)
return err
} }
if err = protojson.Unmarshal(taskBuf, createTaskParams.task); err != nil { if err = protojson.Unmarshal(taskBuf, createTaskParams.task); err != nil {
fmt.Fprintln(os.Stderr, "parse task file error", "err", err) return fmt.Errorf("parse task file error: %w", err)
} }
return doTaskCreate(createTaskParams) return doTaskCreate(createTaskParams)
@@ -69,15 +66,12 @@ func doTaskCreate(createTaskParams createTaskParams) error {
} }
res, err := createTaskParams.saasHttp.TaskCreate(saasReq) res, err := createTaskParams.saasHttp.TaskCreate(saasReq)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "submit Create Task error", "err", err) return fmt.Errorf("Submit Command error: %w", err)
return err
} }
if res.Code != saasapi.ErrorCode_SUCC { if res.Code != saasapi.ErrorCode_SUCC {
fmt.Fprintln(os.Stderr, "task create failed", "code", res.Code, "status", res.Status) return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
return nil
} }
taskRes := res.GetTaskCreateRes() taskRes := res.GetTaskCreateRes()

View File

@@ -4,10 +4,9 @@ import (
"flag" "flag"
"fmt" "fmt"
"net/http" "net/http"
"os"
"e.coding.net/rta/public/saasapi" "git.algo.com.cn/public/saasapi"
"e.coding.net/rta/public/saasapi/pkg/saashttp" "git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/protojson"
) )
@@ -22,8 +21,7 @@ func RunTaskDelete(args ...string) error {
sha256 := paramSha256(fs) sha256 := paramSha256(fs)
if err := fs.Parse(args); err != nil { if err := fs.Parse(args); err != nil {
fmt.Fprintln(os.Stderr, "command line parse error", "err", err) return fmt.Errorf("Command line parse error: %w", err)
return err
} }
if fs.NArg() > 0 || len(*sha256) == 0 { if fs.NArg() > 0 || len(*sha256) == 0 {
@@ -33,8 +31,7 @@ func RunTaskDelete(args ...string) error {
cfg, err := LoadConfigFile(*cfgFile) cfg, err := LoadConfigFile(*cfgFile)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "LoadConfigFile error", "err", err) return fmt.Errorf("LoadConfigFile error: %w", err)
return err
} }
deleteTaskParams := deleteTaskParams{ deleteTaskParams := deleteTaskParams{
@@ -46,15 +43,11 @@ func RunTaskDelete(args ...string) error {
}, },
} }
taskRes, err := doTaskDelete(deleteTaskParams) return doTaskDelete(deleteTaskParams)
if err != nil {
fmt.Printf("task res: %v\n", protojson.Format(taskRes))
}
return err
} }
func doTaskDelete(deleteTaskParams deleteTaskParams) (*saasapi.Task, error) { func doTaskDelete(deleteTaskParams deleteTaskParams) error {
saasReq := &saasapi.SaasReq{ saasReq := &saasapi.SaasReq{
Cmd: &saasapi.SaasReq_TaskDelete{ Cmd: &saasapi.SaasReq_TaskDelete{
TaskDelete: &saasapi.TaskDelete{ TaskDelete: &saasapi.TaskDelete{
@@ -65,17 +58,14 @@ func doTaskDelete(deleteTaskParams deleteTaskParams) (*saasapi.Task, error) {
res, err := deleteTaskParams.saasHttp.TaskDelete(saasReq) res, err := deleteTaskParams.saasHttp.TaskDelete(saasReq)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "submit Task delete error", "err", err) return fmt.Errorf("Submit Command error: %w", err)
return nil, err
} }
if res.Code != saasapi.ErrorCode_SUCC { if res.Code != saasapi.ErrorCode_SUCC {
err = fmt.Errorf("task delete failed. code:%v, status:%v", res.Code, res.Status) return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
fmt.Fprintln(os.Stderr, err)
return nil, err
} }
taskRes := res.GetTaskDeleteRes() taskRes := res.GetTaskDeleteRes()
fmt.Println(protojson.Format(taskRes)) fmt.Printf("task res: %v\n", protojson.Format(taskRes))
return taskRes, nil return nil
} }

View File

@@ -7,8 +7,8 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"e.coding.net/rta/public/saasapi" "git.algo.com.cn/public/saasapi"
"e.coding.net/rta/public/saasapi/pkg/saashttp" "git.algo.com.cn/public/saasapi/pkg/saashttp"
) )
type downloadTaskParams struct { type downloadTaskParams struct {
@@ -24,8 +24,7 @@ func RunTaskDownload(args ...string) error {
destPath := paramDestPath(fs) destPath := paramDestPath(fs)
if err := fs.Parse(args); err != nil { if err := fs.Parse(args); err != nil {
fmt.Fprintln(os.Stderr, "command line parse error", "err", err) return fmt.Errorf("Command line parse error: %w", err)
return err
} }
if fs.NArg() > 0 || len(*sha256) == 0 || len(*destPath) == 0 { if fs.NArg() > 0 || len(*sha256) == 0 || len(*destPath) == 0 {
@@ -35,8 +34,7 @@ func RunTaskDownload(args ...string) error {
cfg, err := LoadConfigFile(*cfgFile) cfg, err := LoadConfigFile(*cfgFile)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "LoadConfigFile error", "err", err) return fmt.Errorf("LoadConfigFile error: %w", err)
return err
} }
downloadTaskParams := downloadTaskParams{ downloadTaskParams := downloadTaskParams{
@@ -63,9 +61,7 @@ func doTaskDownload(downloadTaskParams downloadTaskParams) error {
} }
if len(taskInfo.GetSourcePath()) == 0 { if len(taskInfo.GetSourcePath()) == 0 {
err = fmt.Errorf("task download failed. task info source path is empty") return fmt.Errorf("download task failed: %w, task info source path is empty", err)
fmt.Fprintln(os.Stderr, err)
return err
} }
totalFiles := len(taskInfo.GetTaskFileInfos()) totalFiles := len(taskInfo.GetTaskFileInfos())
@@ -105,9 +101,7 @@ func doTaskDownload(downloadTaskParams downloadTaskParams) error {
} }
if blockRes.GetCode() != saasapi.ErrorCode_SUCC { if blockRes.GetCode() != saasapi.ErrorCode_SUCC {
err = fmt.Errorf("download block error, code %d, msg %s", blockRes.GetCode(), blockRes.GetStatus()) return fmt.Errorf("download block error, code %d, msg %s", blockRes.GetCode(), blockRes.GetStatus())
fmt.Fprintln(os.Stderr, err)
return err
} else { } else {
fmt.Printf("download block success. file: %v, sha256 %v. block %v/%v, file %v/%v\n", fmt.Printf("download block success. file: %v, sha256 %v. block %v/%v, file %v/%v\n",
finfo.GetFileName(), binfo.GetBlockSha256(), finfo.GetFileName(), binfo.GetBlockSha256(),

View File

@@ -4,10 +4,9 @@ import (
"flag" "flag"
"fmt" "fmt"
"net/http" "net/http"
"os"
"e.coding.net/rta/public/saasapi" "git.algo.com.cn/public/saasapi"
"e.coding.net/rta/public/saasapi/pkg/saashttp" "git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/protojson"
) )
@@ -17,13 +16,12 @@ type infoTaskParams struct {
} }
func RunTaskInfo(args ...string) error { func RunTaskInfo(args ...string) error {
fs := flag.NewFlagSet("create", flag.ExitOnError) fs := flag.NewFlagSet("info", flag.ExitOnError)
cfgFile := paramConfig(fs) cfgFile := paramConfig(fs)
sha256 := paramSha256(fs) sha256 := paramSha256(fs)
if err := fs.Parse(args); err != nil { if err := fs.Parse(args); err != nil {
fmt.Fprintln(os.Stderr, "command line parse error", "err", err) return fmt.Errorf("Command line parse error: %w", err)
return err
} }
if fs.NArg() > 0 || len(*sha256) == 0 { if fs.NArg() > 0 || len(*sha256) == 0 {
@@ -33,8 +31,7 @@ func RunTaskInfo(args ...string) error {
cfg, err := LoadConfigFile(*cfgFile) cfg, err := LoadConfigFile(*cfgFile)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "LoadConfigFile error", "err", err) return fmt.Errorf("LoadConfigFile error: %w", err)
return err
} }
infoTaskParams := infoTaskParams{ infoTaskParams := infoTaskParams{
@@ -46,12 +43,9 @@ func RunTaskInfo(args ...string) error {
}, },
} }
taskRes, err := doTaskInfo(infoTaskParams) _, err = doTaskInfo(infoTaskParams)
if err != nil {
fmt.Printf("task res: %v\n", protojson.Format(taskRes))
}
return err return err
} }
func doTaskInfo(infoTaskParams infoTaskParams) (*saasapi.Task, error) { func doTaskInfo(infoTaskParams infoTaskParams) (*saasapi.Task, error) {
@@ -65,17 +59,15 @@ func doTaskInfo(infoTaskParams infoTaskParams) (*saasapi.Task, error) {
res, err := infoTaskParams.saasHttp.TaskInfo(saasReq) res, err := infoTaskParams.saasHttp.TaskInfo(saasReq)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "submit Task info error", "err", err) return nil, fmt.Errorf("Submit Command error: %w", err)
return nil, err
} }
if res.Code != saasapi.ErrorCode_SUCC { if res.Code != saasapi.ErrorCode_SUCC {
err = fmt.Errorf("task info failed. code:%v, status:%v", res.Code, res.Status) return nil, fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
fmt.Fprintln(os.Stderr, err)
return nil, err
} }
taskRes := res.GetTaskInfoRes() taskRes := res.GetTaskInfoRes()
fmt.Println(protojson.Format(taskRes)) fmt.Printf("task res: %v\n", protojson.Format(taskRes))
return taskRes, nil return taskRes, nil
} }

View File

@@ -4,10 +4,9 @@ import (
"flag" "flag"
"fmt" "fmt"
"net/http" "net/http"
"os"
"e.coding.net/rta/public/saasapi" "git.algo.com.cn/public/saasapi"
"e.coding.net/rta/public/saasapi/pkg/saashttp" "git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/protojson"
) )
@@ -17,13 +16,12 @@ type listTaskParams struct {
} }
func RunTaskList(args ...string) error { func RunTaskList(args ...string) error {
fs := flag.NewFlagSet("create", flag.ExitOnError) fs := flag.NewFlagSet("list", flag.ExitOnError)
cfgFile := paramConfig(fs) cfgFile := paramConfig(fs)
filter := paramFilterStatus(fs) filter := paramFilterStatus(fs)
if err := fs.Parse(args); err != nil { if err := fs.Parse(args); err != nil {
fmt.Fprintln(os.Stderr, "command line parse error", "err", err) return fmt.Errorf("Command line parse error: %w", err)
return err
} }
if fs.NArg() > 0 { if fs.NArg() > 0 {
@@ -33,8 +31,7 @@ func RunTaskList(args ...string) error {
cfg, err := LoadConfigFile(*cfgFile) cfg, err := LoadConfigFile(*cfgFile)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "LoadConfigFile error", "err", err) return fmt.Errorf("LoadConfigFile error: %w", err)
return err
} }
listTaskParams := listTaskParams{ listTaskParams := listTaskParams{
@@ -71,15 +68,12 @@ func doTaskList(listTaskParams listTaskParams) error {
} }
res, err := listTaskParams.saasHttp.TaskList(saasReq) res, err := listTaskParams.saasHttp.TaskList(saasReq)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "submit List Task error", "err", err) return fmt.Errorf("Submit Command error: %w", err)
return err
} }
if res.Code != saasapi.ErrorCode_SUCC { if res.Code != saasapi.ErrorCode_SUCC {
fmt.Fprintln(os.Stderr, "task list failed", "code", res.Code, "status", res.Status) return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
return nil
} }
taskRes := res.GetTaskListRes() taskRes := res.GetTaskListRes()

View File

@@ -13,7 +13,7 @@ import (
"strings" "strings"
"sync" "sync"
"e.coding.net/rta/public/saasapi" "git.algo.com.cn/public/saasapi"
"google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/protojson"
) )
@@ -55,8 +55,7 @@ func RunTaskMake(args ...string) error {
ds := paramDataSpaceId(fs) ds := paramDataSpaceId(fs)
if err := fs.Parse(args); err != nil { if err := fs.Parse(args); err != nil {
fmt.Fprintln(os.Stderr, "command line parse error", "err", err) return fmt.Errorf("Command line parse error: %w", err)
return err
} }
if fs.NArg() > 0 || len(*sourcePath) == 0 || len(*hashFile) == 0 || len(*ds) == 0 { if fs.NArg() > 0 || len(*sourcePath) == 0 || len(*hashFile) == 0 || len(*ds) == 0 {
@@ -64,9 +63,8 @@ func RunTaskMake(args ...string) error {
return nil return nil
} }
if strings.ToLower(*ds) == "openid" && len(*appid) == 0 { if strings.ToLower(*ds) == "wuid" && len(*appid) == 0 {
fmt.Fprintln(os.Stderr, "appid must be set when data space is openid") return fmt.Errorf("appid must be set when data space is wuid")
return nil
} }
blockSizeNum, err := ParseByteSize(*blockSize) blockSizeNum, err := ParseByteSize(*blockSize)
@@ -74,12 +72,10 @@ func RunTaskMake(args ...string) error {
fmt.Fprintln(os.Stderr, "Error parsing block size", "err", err) fmt.Fprintln(os.Stderr, "Error parsing block size", "err", err)
fmt.Fprintln(os.Stderr, "Using default 200M") fmt.Fprintln(os.Stderr, "Using default 200M")
blockSizeNum = 200 * 1024 * 1024 blockSizeNum = 200 * 1024 * 1024
} }
if blockSizeNum < blockSizeMin || blockSizeNum > blockSizeMax { if blockSizeNum < blockSizeMin || blockSizeNum > blockSizeMax {
fmt.Fprintln(os.Stderr, "block size error", "min", blockSizeMin, "max", blockSizeMax) return fmt.Errorf("block size error. min: %v, max: %v, current: %v", blockSizeMin, blockSizeMax, blockSizeNum)
return nil
} }
makeTaskParams := &makeTaskParams{ makeTaskParams := &makeTaskParams{

View File

@@ -4,10 +4,9 @@ import (
"flag" "flag"
"fmt" "fmt"
"net/http" "net/http"
"os"
"e.coding.net/rta/public/saasapi" "git.algo.com.cn/public/saasapi"
"e.coding.net/rta/public/saasapi/pkg/saashttp" "git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/protojson"
) )
@@ -17,13 +16,12 @@ type runTaskParams struct {
} }
func RunTaskRun(args ...string) error { func RunTaskRun(args ...string) error {
fs := flag.NewFlagSet("create", flag.ExitOnError) fs := flag.NewFlagSet("run", flag.ExitOnError)
cfgFile := paramConfig(fs) cfgFile := paramConfig(fs)
sha256 := paramSha256(fs) sha256 := paramSha256(fs)
if err := fs.Parse(args); err != nil { if err := fs.Parse(args); err != nil {
fmt.Fprintln(os.Stderr, "command line parse error", "err", err) return fmt.Errorf("Command line parse error: %w", err)
return err
} }
if fs.NArg() > 0 || len(*sha256) == 0 { if fs.NArg() > 0 || len(*sha256) == 0 {
@@ -33,8 +31,7 @@ func RunTaskRun(args ...string) error {
cfg, err := LoadConfigFile(*cfgFile) cfg, err := LoadConfigFile(*cfgFile)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "LoadConfigFile error", "err", err) return fmt.Errorf("LoadConfigFile error: %w", err)
return err
} }
runTaskParams := runTaskParams{ runTaskParams := runTaskParams{
@@ -61,14 +58,11 @@ func doTaskRun(runTaskParams runTaskParams) error {
res, err := runTaskParams.saasHttp.TaskRun(saasReq) res, err := runTaskParams.saasHttp.TaskRun(saasReq)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "submit Task run error", "err", err) return fmt.Errorf("Submit Command error: %w", err)
return err
} }
if res.Code != saasapi.ErrorCode_SUCC { if res.Code != saasapi.ErrorCode_SUCC {
err = fmt.Errorf("task run failed. code:%v, status:%v", res.Code, res.Status) return fmt.Errorf("Command failed. code:%v, status:%v", res.Code, res.Status)
fmt.Fprintln(os.Stderr, err)
return err
} }
fmt.Println("task run success", protojson.Format(res)) fmt.Println("task run success", protojson.Format(res))

View File

@@ -7,8 +7,8 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"e.coding.net/rta/public/saasapi" "git.algo.com.cn/public/saasapi"
"e.coding.net/rta/public/saasapi/pkg/saashttp" "git.algo.com.cn/public/saasapi/pkg/saashttp"
) )
type uploadTaskParams struct { type uploadTaskParams struct {
@@ -22,8 +22,7 @@ func RunTaskUpload(args ...string) error {
sha256 := paramSha256(fs) sha256 := paramSha256(fs)
if err := fs.Parse(args); err != nil { if err := fs.Parse(args); err != nil {
fmt.Fprintln(os.Stderr, "command line parse error", "err", err) return fmt.Errorf("Command line parse error: %w", err)
return err
} }
if fs.NArg() > 0 || len(*sha256) == 0 { if fs.NArg() > 0 || len(*sha256) == 0 {
@@ -33,8 +32,7 @@ func RunTaskUpload(args ...string) error {
cfg, err := LoadConfigFile(*cfgFile) cfg, err := LoadConfigFile(*cfgFile)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "LoadConfigFile error", "err", err) return fmt.Errorf("LoadConfigFile error: %w", err)
return err
} }
uploadTaskParams := uploadTaskParams{ uploadTaskParams := uploadTaskParams{
@@ -47,8 +45,8 @@ func RunTaskUpload(args ...string) error {
} }
return doTaskUpload(uploadTaskParams) return doTaskUpload(uploadTaskParams)
} }
func doTaskUpload(uploadTaskParams uploadTaskParams) error { func doTaskUpload(uploadTaskParams uploadTaskParams) error {
infoTaskParams := infoTaskParams{ infoTaskParams := infoTaskParams{
taskSha256: uploadTaskParams.taskSha256, taskSha256: uploadTaskParams.taskSha256,
@@ -94,9 +92,7 @@ func doTaskUpload(uploadTaskParams uploadTaskParams) error {
} }
if blockRes.GetCode() != saasapi.ErrorCode_SUCC { if blockRes.GetCode() != saasapi.ErrorCode_SUCC {
err = fmt.Errorf("upload block error, code %d, msg %s", blockRes.GetCode(), blockRes.GetStatus()) return fmt.Errorf("upload block error, code %d, msg %s", blockRes.GetCode(), blockRes.GetStatus())
fmt.Fprintln(os.Stderr, err)
return err
} else { } else {
fmt.Printf("upload block success. file: %v, sha256 %v. block %v/%v, file %v/%v\n", fmt.Printf("upload block success. file: %v, sha256 %v. block %v/%v, file %v/%v\n",
finfo.GetFileName(), binfo.GetBlockSha256(), finfo.GetFileName(), binfo.GetBlockSha256(),

View File

@@ -1,25 +0,0 @@
package main
import (
"os"
"syscall"
"unsafe"
)
// https://man7.org/linux/man-pages/man2/TIOCSWINSZ.2const.html
// winSize console窗口大小
type winSize struct {
wsRow uint16
wsCols uint16
wsXPixels uint16
wxYPixels uint16
}
// getConsoleSize 获取控制台窗口大小
func getConsoleSize() (cols, rows int) {
var sz winSize
_, _, _ = syscall.Syscall(syscall.SYS_IOCTL,
os.Stdout.Fd(), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&sz)))
return int(sz.wsCols), int(sz.wsRow)
}

View File

@@ -9,8 +9,8 @@ import (
"path" "path"
"strings" "strings"
"e.coding.net/rta/public/saasapi" "git.algo.com.cn/public/saasapi"
"e.coding.net/rta/public/saasapi/pkg/saashttp" "git.algo.com.cn/public/saasapi/pkg/saashttp"
"google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/protojson"
) )
@@ -34,8 +34,7 @@ func RunWrite(args ...string) error {
clear := paramClear(fs) clear := paramClear(fs)
if err := fs.Parse(args); err != nil { if err := fs.Parse(args); err != nil {
fmt.Fprintln(os.Stderr, "command line parse error", "err", err) return fmt.Errorf("Command line parse error: %w", err)
return err
} }
if fs.NArg() > 0 || len(*sourcePath) == 0 || len(*ds) == 0 { if fs.NArg() > 0 || len(*sourcePath) == 0 || len(*ds) == 0 {
@@ -43,15 +42,14 @@ func RunWrite(args ...string) error {
return nil return nil
} }
if strings.ToLower(*ds) == "openid" && len(*appid) == 0 { if strings.ToLower(*ds) == "wuid" && len(*appid) == 0 {
fmt.Fprintln(os.Stderr, "appid must be set when data space is openid") fmt.Fprintln(os.Stderr, "appid must be set when data space is wuid")
return nil return nil
} }
cfg, err := LoadConfigFile(*cfgFile) cfg, err := LoadConfigFile(*cfgFile)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "load config file error", "err", err) return fmt.Errorf("LoadConfigFile error: %w", err)
return err
} }
writeParams := writeParams{ writeParams := writeParams{
@@ -74,8 +72,7 @@ func RunWrite(args ...string) error {
func doWrite(writeParams writeParams) error { func doWrite(writeParams writeParams) error {
fsInfo, err := os.Stat(writeParams.sourcePath) fsInfo, err := os.Stat(writeParams.sourcePath)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "file stat error", "err", err) return fmt.Errorf("file stat error: %w", err)
return err
} }
if !fsInfo.IsDir() { if !fsInfo.IsDir() {
@@ -86,8 +83,7 @@ func doWrite(writeParams writeParams) error {
// 读取目录下信息 // 读取目录下信息
dirEntry, err := os.ReadDir(writeParams.sourcePath) dirEntry, err := os.ReadDir(writeParams.sourcePath)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "read dir error", "err", err) return fmt.Errorf("read dir error: %w", err)
return err
} }
// 遍历目录 // 遍历目录
@@ -107,8 +103,7 @@ func doLoadFileToWrite(writeParams writeParams) error {
// 读取文件并按行遍历,以\t分割为两列第一列为userid第二列解析为string数组 // 读取文件并按行遍历,以\t分割为两列第一列为userid第二列解析为string数组
file, err := os.Open(writeParams.sourcePath) file, err := os.Open(writeParams.sourcePath)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "open file error", "file", writeParams.sourcePath, "err", err) return fmt.Errorf("open file error: %w. file: %v", err, writeParams.sourcePath)
return err
} }
defer file.Close() defer file.Close()
@@ -127,8 +122,7 @@ func doLoadFileToWrite(writeParams writeParams) error {
} }
saasWriteItem := &saasapi.WriteItem{} saasWriteItem := &saasapi.WriteItem{}
if err = protojson.Unmarshal([]byte(line), saasWriteItem); err != nil { if err = protojson.Unmarshal([]byte(line), saasWriteItem); err != nil {
fmt.Fprintln(os.Stderr, "protojson unmashal error", "file", writeParams.sourcePath, "line", total, "err", err) return fmt.Errorf("protojson unmashal error: %w. file: %v line: %v", err, writeParams.sourcePath, total)
return err
} }
saasWriteItems = append(saasWriteItems, saasWriteItem) saasWriteItems = append(saasWriteItems, saasWriteItem)
@@ -171,15 +165,12 @@ func submitWrite(writeParams writeParams, saasWriteCmds []*saasapi.WriteItem) (e
write.WriteItems = saasWriteCmds write.WriteItems = saasWriteCmds
res, err := writeParams.saasHttp.Write(saasReq) res, err := writeParams.saasHttp.Write(saasReq)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "submit write error", "err", err) return 0, fmt.Errorf("Submit Command error: %w", err)
return
} }
if res.GetCode() != saasapi.ErrorCode_SUCC { if res.GetCode() != saasapi.ErrorCode_SUCC {
err = fmt.Errorf("write failed. code:%v, status:%v", res.GetCode(), res.GetStatus()) err = fmt.Errorf("write failed. code:%v, status:%v", res.GetCode(), res.GetStatus())
fmt.Fprintln(os.Stderr, protojson.Format(res))
return return
} }

1
datasample/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
_*

1
datasample/test.txt Normal file
View File

@@ -0,0 +1 @@
{"userid":"test_user", "writeBytes": {"bytes": "AQ==", "index1": "1"}, "writeUint32s": {"uint32s": [112547657,28270208],"index1": "3"}}

2
datasample/testv2.txt Normal file
View File

@@ -0,0 +1,2 @@
{"userid":"test_user", "bytesKv": {"1": 1,"2": 2,"3": 3,"4": 4,"5": 50,"6": 6,"40": 40,"55": 55,"100": 100}, "uint32sKv": {"1": 100000,"2": 200000,"3": 300000,"4": 400000,"5": 500000,"6": 600000,"55": 5500000,"100": 10000000},"flagsWithExpireKv": {"1": {"flag": true,"expire": 1865854386},"2": {"flag": false,"expire": 1865854386}, "64": {"expire": 1765854386}}}
{"userid":"test_succ", "bytesKv": {"1": 1,"2": 2,"3": 3,"4": 4,"5": 50,"6": 6,"40": 40,"55": 55}, "uint32sKv": {"1": 100000,"2": 200000,"3": 300000,"4": 400000,"5": 500000,"6": 600000,"55": 5500000},"flagsWithExpireKv": {"1": {"flag": true,"expire": 1865854386},"2": {"flag": false,"expire": 1865854386}}}

9
docker/build_saastool.sh Executable file
View File

@@ -0,0 +1,9 @@
#/bin/sh -v
set -e
docker buildx build --platform linux/amd64 \
-t rta-docker.pkg.coding.net/public/docker/saastool:2026011914 \
-o type=registry \
-f saastool.Dockerfile \
../ ;

View File

@@ -10,3 +10,7 @@ RUN --mount=type=cache,target=/root/.cache/go-build \
FROM rta-docker.pkg.coding.net/public/docker/alpine:latest AS product FROM rta-docker.pkg.coding.net/public/docker/alpine:latest AS product
COPY --from=builder /tmp/saasapi/build/saastool /bin/saastool COPY --from=builder /tmp/saasapi/build/saastool /bin/saastool
EXPOSE 8080
CMD ["saastool", "daemon"]

2
go.mod
View File

@@ -1,4 +1,4 @@
module e.coding.net/rta/public/saasapi module git.algo.com.cn/public/saasapi
go 1.23.4 go 1.23.4

View File

@@ -1,3 +1,8 @@
cd cmd/saastool cd cmd/saastool
go build -o ../../build/saastool go build -o ../../build/saastool
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ../../build/saastool_linux_x64
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o ../../build/saastool_win_x64
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o ../../build/saastool_mac_x64
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o ../../build/saastool_mac_arm64
cd ../../ cd ../../

View File

@@ -1,40 +1,78 @@
package saashttp package saashttp
const ( const (
baseUrl = "https://api.rta.qq.com" baseUrl = "https://api.rta.qq.com"
infoPath = "/saas/info" infoPath = "/saas/info"
writePath = "/saas/write" writePath = "/saas/write"
readPath = "/saas/read" readPath = "/saas/read"
columnWritePath = "/saas/column_write" columnWritePath = "/saas/column_write"
taskCreatePath = "/saas/task/create" resetDSPath = "/saas/resetds"
taskListPath = "/saas/task/list" taskCreatePath = "/saas/task/create"
taskCancelPath = "/saas/task/delete" taskListPath = "/saas/task/list"
taskInfoPath = "/saas/task/info" taskInfoPath = "/saas/task/info"
taskUploadPath = "/saas/task/upload" taskUploadPath = "/saas/task/upload"
taskDownloadPath = "/saas/task/download" taskDownloadPath = "/saas/task/download"
taskDeletePath = "/saas/task/delete" taskDeletePath = "/saas/task/delete"
taskRunPath = "/saas/task/run" taskRunPath = "/saas/task/run"
targetListPath = "/saas/target/list" targetListPath = "/saas/target/list"
bindSetPath = "/saas/bind/set" targetCreatePath = "/saas/target/create"
bindDeletePath = "/saas/bind/delete" targetDeletePath = "/saas/target/delete"
bindSetPath = "/saas/bind/set"
bindDeletePath = "/saas/bind/delete"
scriptDebugPath = "/saas/script/debug"
scriptCreatePath = "/saas/script/create"
scriptListPath = "/saas/script/list"
scriptDeletePath = "/saas/script/delete"
scriptGetPath = "/saas/script/get"
scriptUsePath = "/saas/script/use"
expListPath = "/saas/exp/list"
expGetPath = "/saas/exp/get"
expGrantListPath = "/saas/exp/grant/list"
expGrantAddPath = "/saas/exp/grant/add"
expGrantDeletePath = "/saas/exp/grant/delete"
grantListPath = "/saas/grant/list"
grantAddPath = "/saas/grant/add"
grantDeletePath = "/saas/grant/delete"
) )
type Auth struct {
Account string
Token string
}
type ApiUrls struct { type ApiUrls struct {
BaseUrl string BaseUrl string
InfoPath string InfoPath string
WritePath string WritePath string
ReadPath string ReadPath string
ColumnWritePath string ColumnWritePath string
TaskCreatePath string ResetDSPath string
TaskListPath string TaskCreatePath string
TaskInfoPath string TaskListPath string
TaskDeletePath string TaskInfoPath string
TaskRunPath string TaskDeletePath string
TaskUploadPath string TaskRunPath string
TaskDownloadPath string TaskUploadPath string
TargetListPath string TaskDownloadPath string
BindSetPath string TargetListPath string
BindDeletePath string TargetCreatePath string
TargetDeletePath string
BindSetPath string
BindDeletePath string
ScriptDebugPath string
ScriptCreatePath string
ScriptListPath string
ScriptDeletePath string
ScriptGetPath string
ScriptUsePath string
ExpListPath string
ExpGetPath string
ExpGrantListPath string
ExpGrantAddPath string
ExpGrantDeletePath string
GrantListPath string
GrantAddPath string
GrantDeletePath string
} }
func InitAPIUrl(c *ApiUrls) *ApiUrls { func InitAPIUrl(c *ApiUrls) *ApiUrls {
@@ -44,79 +82,81 @@ func InitAPIUrl(c *ApiUrls) *ApiUrls {
} else { } else {
r.BaseUrl = baseUrl r.BaseUrl = baseUrl
} }
if c.InfoPath != "" { if c.InfoPath != "" {
r.InfoPath = c.InfoPath r.InfoPath = c.InfoPath
} else { } else {
r.InfoPath = infoPath r.InfoPath = infoPath
} }
if c.WritePath != "" { if c.WritePath != "" {
r.WritePath = c.WritePath r.WritePath = c.WritePath
} else { } else {
r.WritePath = writePath r.WritePath = writePath
} }
if c.ReadPath != "" { if c.ReadPath != "" {
r.ReadPath = c.ReadPath r.ReadPath = c.ReadPath
} else { } else {
r.ReadPath = readPath r.ReadPath = readPath
} }
if c.ColumnWritePath != "" { if c.ColumnWritePath != "" {
r.ColumnWritePath = c.ColumnWritePath r.ColumnWritePath = c.ColumnWritePath
} else { } else {
r.ColumnWritePath = columnWritePath r.ColumnWritePath = columnWritePath
} }
if c.ResetDSPath != "" {
r.ResetDSPath = c.ResetDSPath
} else {
r.ResetDSPath = resetDSPath
}
if c.TaskCreatePath != "" { if c.TaskCreatePath != "" {
r.TaskCreatePath = c.TaskCreatePath r.TaskCreatePath = c.TaskCreatePath
} else { } else {
r.TaskCreatePath = taskCreatePath r.TaskCreatePath = taskCreatePath
} }
if c.TaskListPath != "" { if c.TaskListPath != "" {
r.TaskListPath = c.TaskListPath r.TaskListPath = c.TaskListPath
} else { } else {
r.TaskListPath = taskListPath r.TaskListPath = taskListPath
} }
if c.TaskInfoPath != "" { if c.TaskInfoPath != "" {
r.TaskInfoPath = c.TaskInfoPath r.TaskInfoPath = c.TaskInfoPath
} else { } else {
r.TaskInfoPath = taskInfoPath r.TaskInfoPath = taskInfoPath
} }
if c.TaskDeletePath != "" { if c.TaskDeletePath != "" {
r.TaskDeletePath = c.TaskDeletePath r.TaskDeletePath = c.TaskDeletePath
} else { } else {
r.TaskDeletePath = taskDeletePath r.TaskDeletePath = taskDeletePath
} }
if c.TaskRunPath != "" { if c.TaskRunPath != "" {
r.TaskRunPath = c.TaskRunPath r.TaskRunPath = c.TaskRunPath
} else { } else {
r.TaskRunPath = taskRunPath r.TaskRunPath = taskRunPath
} }
if c.TaskUploadPath != "" { if c.TaskUploadPath != "" {
r.TaskUploadPath = c.TaskUploadPath r.TaskUploadPath = c.TaskUploadPath
} else { } else {
r.TaskUploadPath = taskUploadPath r.TaskUploadPath = taskUploadPath
} }
if c.TaskDownloadPath != "" { if c.TaskDownloadPath != "" {
r.TaskDownloadPath = c.TaskDownloadPath r.TaskDownloadPath = c.TaskDownloadPath
} else { } else {
r.TaskDownloadPath = taskDownloadPath r.TaskDownloadPath = taskDownloadPath
} }
if c.TargetListPath != "" { if c.TargetListPath != "" {
r.TargetListPath = c.TargetListPath r.TargetListPath = c.TargetListPath
} else { } else {
r.TargetListPath = targetListPath r.TargetListPath = targetListPath
} }
if c.TargetCreatePath != "" {
r.TargetCreatePath = c.TargetCreatePath
} else {
r.TargetCreatePath = targetCreatePath
}
if c.TargetDeletePath != "" {
r.TargetDeletePath = c.TargetDeletePath
} else {
r.TargetDeletePath = targetDeletePath
}
if c.BindSetPath != "" { if c.BindSetPath != "" {
r.BindSetPath = c.BindSetPath r.BindSetPath = c.BindSetPath
} else { } else {
@@ -129,10 +169,89 @@ func InitAPIUrl(c *ApiUrls) *ApiUrls {
r.BindDeletePath = bindDeletePath r.BindDeletePath = bindDeletePath
} }
if c.ScriptDebugPath != "" {
r.ScriptDebugPath = c.ScriptDebugPath
} else {
r.ScriptDebugPath = scriptDebugPath
}
if c.ScriptCreatePath != "" {
r.ScriptCreatePath = c.ScriptCreatePath
} else {
r.ScriptCreatePath = scriptCreatePath
}
if c.ScriptListPath != "" {
r.ScriptListPath = c.ScriptListPath
} else {
r.ScriptListPath = scriptListPath
}
if c.ScriptDeletePath != "" {
r.ScriptDeletePath = c.ScriptDeletePath
} else {
r.ScriptDeletePath = scriptDeletePath
}
if c.ScriptGetPath != "" {
r.ScriptGetPath = c.ScriptGetPath
} else {
r.ScriptGetPath = scriptGetPath
}
if c.ScriptUsePath != "" {
r.ScriptUsePath = c.ScriptUsePath
} else {
r.ScriptUsePath = scriptUsePath
}
if c.ExpListPath != "" {
r.ExpListPath = c.ExpListPath
} else {
r.ExpListPath = expListPath
}
if c.ExpGetPath != "" {
r.ExpGetPath = c.ExpGetPath
} else {
r.ExpGetPath = expGetPath
}
if c.ExpGrantListPath != "" {
r.ExpGrantListPath = c.ExpGrantListPath
} else {
r.ExpGrantListPath = expGrantListPath
}
if c.ExpGrantAddPath != "" {
r.ExpGrantAddPath = c.ExpGrantAddPath
} else {
r.ExpGrantAddPath = expGrantAddPath
}
if c.ExpGrantDeletePath != "" {
r.ExpGrantDeletePath = c.ExpGrantDeletePath
} else {
r.ExpGrantDeletePath = expGrantDeletePath
}
if c.GrantListPath != "" {
r.GrantListPath = c.GrantListPath
} else {
r.GrantListPath = grantListPath
}
if c.GrantAddPath != "" {
r.GrantAddPath = c.GrantAddPath
} else {
r.GrantAddPath = grantAddPath
}
if c.GrantDeletePath != "" {
r.GrantDeletePath = c.GrantDeletePath
} else {
r.GrantDeletePath = grantDeletePath
}
return r return r
} }
type Auth struct {
Account string
Token string
}

View File

@@ -15,7 +15,7 @@ import (
"strings" "strings"
"time" "time"
"e.coding.net/rta/public/saasapi" "git.algo.com.cn/public/saasapi"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
@@ -53,6 +53,11 @@ func (c *SaasClient) ColumnWrite(saasReq *saasapi.SaasReq) (saasRes *saasapi.Saa
return c.post(postUrl, saasReq) return c.post(postUrl, saasReq)
} }
func (c *SaasClient) ResetDS(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ResetDSPath)
return c.post(postUrl, saasReq)
}
func (c *SaasClient) TaskCreate(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) { func (c *SaasClient) TaskCreate(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.TaskCreatePath) postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.TaskCreatePath)
return c.post(postUrl, saasReq) return c.post(postUrl, saasReq)
@@ -93,6 +98,16 @@ func (c *SaasClient) TargetList(saasReq *saasapi.SaasReq) (saasRes *saasapi.Saas
return c.post(postUrl, saasReq) return c.post(postUrl, saasReq)
} }
func (c *SaasClient) TargetCreate(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.TargetCreatePath)
return c.post(postUrl, saasReq)
}
func (c *SaasClient) TargetDelete(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.TargetDeletePath)
return c.post(postUrl, saasReq)
}
func (c *SaasClient) BindSet(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) { func (c *SaasClient) BindSet(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.BindSetPath) postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.BindSetPath)
return c.post(postUrl, saasReq) return c.post(postUrl, saasReq)
@@ -103,6 +118,51 @@ func (c *SaasClient) BindDelete(saasReq *saasapi.SaasReq) (saasRes *saasapi.Saas
return c.post(postUrl, saasReq) return c.post(postUrl, saasReq)
} }
func (c *SaasClient) ScriptDebug(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ScriptDebugPath)
return c.post(postUrl, saasReq)
}
func (c *SaasClient) ExpList(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ExpListPath)
return c.post(postUrl, saasReq)
}
func (c *SaasClient) ExpGet(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ExpGetPath)
return c.post(postUrl, saasReq)
}
func (c *SaasClient) GrantList(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.GrantListPath)
return c.post(postUrl, saasReq)
}
func (c *SaasClient) GrantAdd(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.GrantAddPath)
return c.post(postUrl, saasReq)
}
func (c *SaasClient) GrantDelete(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.GrantDeletePath)
return c.post(postUrl, saasReq)
}
func (c *SaasClient) ExpGrantList(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ExpGrantListPath)
return c.post(postUrl, saasReq)
}
func (c *SaasClient) ExpGrantAdd(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ExpGrantAddPath)
return c.post(postUrl, saasReq)
}
func (c *SaasClient) ExpGrantDelete(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ExpGrantDeletePath)
return c.post(postUrl, saasReq)
}
func (c *SaasClient) makeUrl(baseUrl, path string, params ...string) string { func (c *SaasClient) makeUrl(baseUrl, path string, params ...string) string {
url, err := url.Parse(baseUrl) url, err := url.Parse(baseUrl)
if err != nil { if err != nil {
@@ -131,14 +191,12 @@ func (c *SaasClient) makeUrl(baseUrl, path string, params ...string) string {
func (c *SaasClient) post(url string, saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) { func (c *SaasClient) post(url string, saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postBuf, err := proto.Marshal(saasReq) postBuf, err := proto.Marshal(saasReq)
if err != nil { if err != nil {
fmt.Println("marshal saas req error", err) return nil, fmt.Errorf("Marshal saas req error. %w", err)
return nil, err
} }
req, err := http.NewRequest("POST", url, bytes.NewBuffer(postBuf)) req, err := http.NewRequest("POST", url, bytes.NewBuffer(postBuf))
if err != nil { if err != nil {
fmt.Println("http new request error", err) return nil, fmt.Errorf("Http new request error. %w", err)
return nil, err
} }
timeStamp := strconv.FormatInt(time.Now().Unix(), 10) timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
@@ -151,30 +209,30 @@ func (c *SaasClient) post(url string, saasReq *saasapi.SaasReq) (saasRes *saasap
req.Header.Add("Content-Type", "application/x-protobuf") req.Header.Add("Content-Type", "application/x-protobuf")
res, err := c.Client.Do(req) res, err := c.Client.Do(req)
if err != nil { if err != nil {
fmt.Println("http send error", err) return nil, fmt.Errorf("Http do request error. %w", err)
return nil, err
} }
defer res.Body.Close() defer res.Body.Close()
if res.StatusCode != 200 {
return nil, fmt.Errorf("NOT 200. %v", res.StatusCode)
}
resBody, err := io.ReadAll(res.Body) resBody, err := io.ReadAll(res.Body)
if err != nil { if err != nil {
fmt.Println("http read body error", err) return nil, fmt.Errorf("Http read body error. %w", err)
return nil, err
} }
saasRes = &saasapi.SaasRes{} saasRes = &saasapi.SaasRes{}
if c.ResponseEncoder == RESPONSE_ENCODER_PROTOBUF { if c.ResponseEncoder == RESPONSE_ENCODER_PROTOBUF {
err = proto.Unmarshal(resBody, saasRes) err = proto.Unmarshal(resBody, saasRes)
if err != nil { if err != nil {
fmt.Println("unmarshal response body to protobuf error", err) return nil, fmt.Errorf("unmarshal response body to protobuf error. %w", err)
return nil, err
} }
} else { } else {
err = json.Unmarshal(resBody, saasRes) err = json.Unmarshal(resBody, saasRes)
if err != nil { if err != nil {
fmt.Println("unmarshal response body to json error", err) return nil, fmt.Errorf("unmarshal response body to json error. %w", err)
return nil, err
} }
} }
@@ -183,39 +241,36 @@ func (c *SaasClient) post(url string, saasReq *saasapi.SaasReq) (saasRes *saasap
func (c *SaasClient) upload(url string, file *os.File, offset int64, size int) (saasRes *saasapi.SaasRes, err error) { func (c *SaasClient) upload(url string, file *os.File, offset int64, size int) (saasRes *saasapi.SaasRes, err error) {
if file == nil { if file == nil {
return nil, fmt.Errorf("file is nil") return nil, fmt.Errorf("file is nil.")
} }
if size <= 0 { if size <= 0 {
return nil, fmt.Errorf("size is invalid") return nil, fmt.Errorf("size is invalid.")
} }
buf := make([]byte, size) buf := make([]byte, size)
n, err := file.ReadAt(buf, offset) n, err := file.ReadAt(buf, offset)
if err != nil { if err != nil {
fmt.Println("read file error", err) return nil, fmt.Errorf("Read file error. %w", err)
return nil, err
} }
if n != size { if n != size {
return nil, fmt.Errorf("read file error") return nil, fmt.Errorf("Read file size not match. %v", n)
} }
var gzBuf bytes.Buffer var gzBuf bytes.Buffer
gz := gzip.NewWriter(&gzBuf) gz := gzip.NewWriter(&gzBuf)
if _, err := gz.Write(buf); err != nil { if _, err := gz.Write(buf); err != nil {
fmt.Println("gzip write error", err) return nil, fmt.Errorf("GZip write error. %w", err)
return nil, err
} }
if err = gz.Close(); err != nil { if err = gz.Close(); err != nil {
return nil, err return nil, fmt.Errorf("GZip close error. %w", err)
} }
req, err := http.NewRequest("POST", url, bytes.NewBuffer(gzBuf.Bytes())) req, err := http.NewRequest("POST", url, bytes.NewBuffer(gzBuf.Bytes()))
if err != nil { if err != nil {
fmt.Println("http new request error", err) return nil, fmt.Errorf("Http new request error. %w", err)
return nil, err
} }
timeStamp := strconv.FormatInt(time.Now().Unix(), 10) timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
@@ -229,30 +284,30 @@ func (c *SaasClient) upload(url string, file *os.File, offset int64, size int) (
req.Header.Add("Content-Encoding", "gzip") req.Header.Add("Content-Encoding", "gzip")
res, err := c.Client.Do(req) res, err := c.Client.Do(req)
if err != nil { if err != nil {
fmt.Println("http send error", err) return nil, fmt.Errorf("Http do request error. %w", err)
return nil, err
} }
defer res.Body.Close() defer res.Body.Close()
if res.StatusCode != 200 {
return nil, fmt.Errorf("NOT 200. %v", res.StatusCode)
}
resBody, err := io.ReadAll(res.Body) resBody, err := io.ReadAll(res.Body)
if err != nil { if err != nil {
fmt.Println("http read body error", err) return nil, fmt.Errorf("http read body error. %w", err)
return nil, err
} }
saasRes = &saasapi.SaasRes{} saasRes = &saasapi.SaasRes{}
if c.ResponseEncoder == RESPONSE_ENCODER_PROTOBUF { if c.ResponseEncoder == RESPONSE_ENCODER_PROTOBUF {
err = proto.Unmarshal(resBody, saasRes) err = proto.Unmarshal(resBody, saasRes)
if err != nil { if err != nil {
fmt.Println("unmarshal response body to protobuf error", err) return nil, fmt.Errorf("unmarshal response body to protobuf error. %w", err)
return nil, err
} }
} else { } else {
err = json.Unmarshal(resBody, saasRes) err = json.Unmarshal(resBody, saasRes)
if err != nil { if err != nil {
fmt.Println("unmarshal response body to json error", err) return nil, fmt.Errorf("unmarshal response body to json error. %w", err)
return nil, err
} }
} }
@@ -261,17 +316,16 @@ func (c *SaasClient) upload(url string, file *os.File, offset int64, size int) (
func (c *SaasClient) download(url string, file *os.File, offset int64, size int) (saasRes *saasapi.SaasRes, err error) { func (c *SaasClient) download(url string, file *os.File, offset int64, size int) (saasRes *saasapi.SaasRes, err error) {
if file == nil { if file == nil {
return nil, fmt.Errorf("file is nil") return nil, fmt.Errorf("file is nil.")
} }
if size <= 0 { if size <= 0 {
return nil, fmt.Errorf("size is invalid") return nil, fmt.Errorf("size is invalid.")
} }
req, err := http.NewRequest("GET", url, bytes.NewBuffer([]byte{})) req, err := http.NewRequest("GET", url, bytes.NewBuffer([]byte{}))
if err != nil { if err != nil {
fmt.Println("http new request error", err) return nil, fmt.Errorf("Http new request error. %w", err)
return nil, err
} }
timeStamp := strconv.FormatInt(time.Now().Unix(), 10) timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
@@ -285,24 +339,20 @@ func (c *SaasClient) download(url string, file *os.File, offset int64, size int)
res, err := c.Client.Do(req) res, err := c.Client.Do(req)
if err != nil { if err != nil {
fmt.Println("http send error", err) return nil, fmt.Errorf("Http do request error. %w", err)
return nil, err
} }
defer res.Body.Close() defer res.Body.Close()
if res.StatusCode != 200 { if res.StatusCode != 200 {
err = fmt.Errorf("NOT 200. %v", res.StatusCode) return nil, fmt.Errorf("http state error. %w", err)
fmt.Println("http state error", err)
return nil, err
} }
bodyReader := res.Body bodyReader := res.Body
if strings.Contains(res.Header.Get("Content-Encoding"), "gzip") { if strings.Contains(res.Header.Get("Content-Encoding"), "gzip") {
gz, err := gzip.NewReader(res.Body) gz, err := gzip.NewReader(res.Body)
if err != nil { if err != nil {
fmt.Println("gzip newreader error", err) return nil, fmt.Errorf("GZip newreader error. %w", err)
return nil, err
} }
defer gz.Close() defer gz.Close()
bodyReader = gz bodyReader = gz
@@ -310,8 +360,7 @@ func (c *SaasClient) download(url string, file *os.File, offset int64, size int)
resBody, err := io.ReadAll(bodyReader) resBody, err := io.ReadAll(bodyReader)
if err != nil { if err != nil {
fmt.Println("read body error", err) return nil, fmt.Errorf("Http read body error. %w", err)
return nil, err
} }
saasRes = &saasapi.SaasRes{} saasRes = &saasapi.SaasRes{}
@@ -319,25 +368,46 @@ func (c *SaasClient) download(url string, file *os.File, offset int64, size int)
if len(resBody) == size { if len(resBody) == size {
file.WriteAt(resBody, offset) file.WriteAt(resBody, offset)
} else { } else {
err = fmt.Errorf("body size error. body:%v, want:%v", len(resBody), size) return nil, fmt.Errorf("body size error. body:%v, want:%v", len(resBody), size)
fmt.Println("http read body error", err)
return nil, err
} }
} else { } else {
if c.ResponseEncoder == RESPONSE_ENCODER_PROTOBUF { if c.ResponseEncoder == RESPONSE_ENCODER_PROTOBUF {
err = proto.Unmarshal(resBody, saasRes) err = proto.Unmarshal(resBody, saasRes)
if err != nil { if err != nil {
fmt.Println("unmarshal response body to protobuf error", err) return nil, fmt.Errorf("unmarshal response body to protobuf error. %w", err)
return nil, err
} }
} else { } else {
err = json.Unmarshal(resBody, saasRes) err = json.Unmarshal(resBody, saasRes)
if err != nil { if err != nil {
fmt.Println("unmarshal response body to json error", err) return nil, fmt.Errorf("unmarshal response body to json error. %w", err)
return nil, err
} }
} }
} }
return saasRes, nil return saasRes, nil
} }
func (c *SaasClient) ScriptCreate(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ScriptCreatePath)
return c.post(postUrl, saasReq)
}
func (c *SaasClient) ScriptList(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ScriptListPath)
return c.post(postUrl, saasReq)
}
func (c *SaasClient) ScriptDelete(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ScriptDeletePath)
return c.post(postUrl, saasReq)
}
func (c *SaasClient) ScriptGet(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ScriptGetPath)
return c.post(postUrl, saasReq)
}
func (c *SaasClient) ScriptUse(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ScriptUsePath)
return c.post(postUrl, saasReq)
}