实验报表授权、GEO支持

This commit is contained in:
algotao
2025-12-13 09:16:21 +08:00
parent cbbeb04ee5
commit 765e75937d
14 changed files with 868 additions and 258 deletions

660
cmd.pb.go

File diff suppressed because it is too large Load Diff

View File

@@ -39,6 +39,9 @@ message SaasReq {
ExpList exp_list = 100; // 列出实验 ExpList exp_list = 100; // 列出实验
ExpGet exp_get = 101; // 获取实验报表 ExpGet exp_get = 101; // 获取实验报表
ExpGrantList exp_grant_list = 102; // 列出访问实验报表授权
ExpGrant exp_grant_add = 103; // 授权他人访问实验报表
ExpGrant exp_grant_delete = 104; // 取消他人访问实验报表
} }
} }
@@ -260,6 +263,14 @@ message ExpGet {
uint32 total_flag = 30; // 是否汇总0=不汇总1=汇总 uint32 total_flag = 30; // 是否汇总0=不汇总1=汇总
} }
message ExpGrantList {
}
message ExpGrant {
uint32 target_account_id = 1; // sRTA授权目标账号ID
}
// SaasRes 命令返回 // SaasRes 命令返回
message SaasRes { message SaasRes {
ErrorCode code = 1; // 返回码 ErrorCode code = 1; // 返回码
@@ -296,12 +307,16 @@ message SaasRes {
ExpListRes exp_list_res = 100; // 实验列表返回 ExpListRes exp_list_res = 100; // 实验列表返回
ExpGetRes exp_get_res = 101; // 实验报表返回 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 { message DataSpace {
repeated string did = 1; // 设备ID区 repeated string did = 1; // 设备ID区
repeated string wuid = 2; // OpenID区 repeated string wuid = 2; // OpenID区
repeated string geo = 7; // GEO区
} }
// InfoRes 账号信息返回 // InfoRes 账号信息返回
@@ -471,6 +486,7 @@ message ExpGetRes {
repeated ExpData exp_data = 1; // 实验数据 repeated ExpData exp_data = 1; // 实验数据
} }
// ExpData 实验数据
message ExpData { message ExpData {
uint64 time = 1; // 日期 uint64 time = 1; // 日期
uint32 bucket_id = 2; // 分桶ID uint32 bucket_id = 2; // 分桶ID
@@ -479,6 +495,7 @@ message ExpData {
map<string, uint64> group = 5; // 分组 map<string, uint64> group = 5; // 分组
} }
// ExpBaseFields 基础实验字段
message ExpBaseFields { message ExpBaseFields {
double cost = 1; // 花费 double cost = 1; // 花费
int64 exposure = 2; // 曝光量 int64 exposure = 2; // 曝光量
@@ -493,6 +510,12 @@ message ExpBaseFields {
int64 conversion_second = 11; // 深层转化量 int64 conversion_second = 11; // 深层转化量
} }
// ExpGrantListRes 授权列表返回
message ExpGrantListRes {
repeated ExpGrant from = 1; // 被授权列表
repeated ExpGrant to = 2; // 向外授权列表
}
// ErrorCode 返回码 // ErrorCode 返回码
enum ErrorCode { enum ErrorCode {
SUCC = 0; // 成功 SUCC = 0; // 成功

View File

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

View File

@@ -221,9 +221,9 @@ func (d *Daemon) parsePublicParams(r *http.Request) (*daemonPublicParams, error)
params.ds = strings.ToLower(strings.TrimSpace(q.Get("ds"))) params.ds = strings.ToLower(strings.TrimSpace(q.Get("ds")))
switch params.ds { switch params.ds {
case "did", "wuid": case "did", "wuid", "geo":
default: default:
return nil, fmt.Errorf("ds must use did/wuid. current is %v", params.ds) return nil, fmt.Errorf("ds must use did/wuid/geo. current is %v", params.ds)
} }
params.appid = strings.TrimSpace(q.Get("appid")) params.appid = strings.TrimSpace(q.Get("appid"))

View File

@@ -17,6 +17,8 @@ func RunExp(args ...string) error {
return RunExpList(args...) return RunExpList(args...)
case "get": case "get":
return RunExpGet(args...) return RunExpGet(args...)
case "grant":
return RunExpGrant(args...)
default: default:
err := fmt.Errorf(`unknown command "%s"`+"\n"+`Run 'saastool exp help' for usage`, name) err := fmt.Errorf(`unknown command "%s"`+"\n"+`Run 'saastool exp help' for usage`, name)
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)
@@ -31,11 +33,12 @@ func RunExpHelp(args ...string) error {
} }
const expUsage = ` const expUsage = `
Usage: saastoola exp COMMAND [OPTIONS] Usage: saastool exp COMMAND [OPTIONS]
Commands: Commands:
list List exps list List exps
get Get exp report get Get exp report
grant Experiment authorization management
"help" is the default command. "help" is the default command.

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

@@ -0,0 +1,40 @@
package main
import (
"fmt"
"os"
"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:
err := fmt.Errorf(`unknown command "%s"`+"\n"+`Run 'saastool exp grant help' for usage`, name)
fmt.Fprintln(os.Stderr, err)
return err
}
}
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,81 @@
package main
import (
"flag"
"fmt"
"net/http"
"os"
"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 {
fmt.Fprintln(os.Stderr, "command line parse error", "err", err)
return err
}
if fs.NArg() > 0 {
fs.PrintDefaults()
return nil
}
if *srtaAccountId == 0 {
fmt.Fprintln(os.Stderr, "Error: sRTA account ID is required")
fs.PrintDefaults()
return fmt.Errorf("sRTA account ID is required")
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
fmt.Fprintln(os.Stderr, "LoadConfigFile error", "err", err)
return 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 {
fmt.Fprintln(os.Stderr, "submit Exp Grant Add error", "err", err)
return err
}
if res.Code != saasapi.ErrorCode_SUCC {
fmt.Fprintln(os.Stderr, "Exp grant add failed", "code", res.Code, "status", res.Status)
return nil
}
expGrantRes := res.GetExpGrantAddRes()
fmt.Printf("exp grant add res: %v\n", protojson.Format(expGrantRes))
return nil
}

View File

@@ -0,0 +1,81 @@
package main
import (
"flag"
"fmt"
"net/http"
"os"
"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 {
fmt.Fprintln(os.Stderr, "command line parse error", "err", err)
return err
}
if fs.NArg() > 0 {
fs.PrintDefaults()
return nil
}
if *srtaAccountId == 0 {
fmt.Fprintln(os.Stderr, "Error: sRTA account ID is required")
fs.PrintDefaults()
return fmt.Errorf("sRTA account ID is required")
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
fmt.Fprintln(os.Stderr, "LoadConfigFile error", "err", err)
return 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 {
fmt.Fprintln(os.Stderr, "submit Exp Grant Delete error", "err", err)
return err
}
if res.Code != saasapi.ErrorCode_SUCC {
fmt.Fprintln(os.Stderr, "Exp grant delete failed", "code", res.Code, "status", res.Status)
return nil
}
expGrantRes := res.GetExpGrantDeleteRes()
fmt.Printf("exp grant delete res: %v\n", protojson.Format(expGrantRes))
return nil
}

View File

@@ -0,0 +1,70 @@
package main
import (
"flag"
"fmt"
"net/http"
"os"
"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 {
fmt.Fprintln(os.Stderr, "command line parse error", "err", err)
return err
}
if fs.NArg() > 0 {
fs.PrintDefaults()
return nil
}
cfg, err := LoadConfigFile(*cfgFile)
if err != nil {
fmt.Fprintln(os.Stderr, "LoadConfigFile error", "err", err)
return 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 {
fmt.Fprintln(os.Stderr, "submit Exp Grant List error", "err", err)
return err
}
if res.Code != saasapi.ErrorCode_SUCC {
fmt.Fprintln(os.Stderr, "Exp grant list failed", "code", res.Code, "status", res.Status)
return nil
}
expGrantRes := res.GetExpGrantListRes()
fmt.Printf("exp grant list res: %v\n", protojson.Format(expGrantRes))
return nil
}

View File

@@ -74,7 +74,6 @@ 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 {

View File

@@ -4,7 +4,7 @@ set -e
docker buildx build --platform linux/amd64 \ docker buildx build --platform linux/amd64 \
-t rta-docker.pkg.coding.net/public/docker/saastool:latest \ -t rta-docker.pkg.coding.net/public/docker/saastool:latest \
-t rta-docker.pkg.coding.net/public/docker/saastool:2025112312 \ -t rta-docker.pkg.coding.net/public/docker/saastool:2025121210 \
-o type=registry \ -o type=registry \
-f saastool.Dockerfile \ -f saastool.Dockerfile \
../ ; ../ ;

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,34 +1,37 @@
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" taskCreatePath = "/saas/task/create"
taskListPath = "/saas/task/list" 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"
targetCreatePath = "/saas/target/create" targetCreatePath = "/saas/target/create"
targetDeletePath = "/saas/target/delete" targetDeletePath = "/saas/target/delete"
bindSetPath = "/saas/bind/set" bindSetPath = "/saas/bind/set"
bindDeletePath = "/saas/bind/delete" bindDeletePath = "/saas/bind/delete"
scriptRunPath = "/saas/script/run" scriptRunPath = "/saas/script/run"
scriptCreatePath = "/saas/script/create" scriptCreatePath = "/saas/script/create"
scriptListPath = "/saas/script/list" scriptListPath = "/saas/script/list"
scriptDeletePath = "/saas/script/delete" scriptDeletePath = "/saas/script/delete"
scriptGetPath = "/saas/script/get" scriptGetPath = "/saas/script/get"
scriptUsePath = "/saas/script/use" scriptUsePath = "/saas/script/use"
expListPath = "/saas/exp/list" expListPath = "/saas/exp/list"
expGetPath = "/saas/exp/get" expGetPath = "/saas/exp/get"
grantListPath = "/saas/grant/list" expGrantListPath = "/saas/exp/grant/list"
grantAddPath = "/saas/grant/add" expGrantAddPath = "/saas/exp/grant/add"
grantDeletePath = "/saas/grant/delete" expGrantDeletePath = "/saas/exp/grant/delete"
grantListPath = "/saas/grant/list"
grantAddPath = "/saas/grant/add"
grantDeletePath = "/saas/grant/delete"
) )
type Auth struct { type Auth struct {
@@ -37,34 +40,37 @@ type Auth struct {
} }
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 TaskCreatePath string
TaskListPath string TaskListPath string
TaskInfoPath string TaskInfoPath string
TaskDeletePath string TaskDeletePath string
TaskRunPath string TaskRunPath string
TaskUploadPath string TaskUploadPath string
TaskDownloadPath string TaskDownloadPath string
TargetListPath string TargetListPath string
TargetCreatePath string TargetCreatePath string
TargetDeletePath string TargetDeletePath string
BindSetPath string BindSetPath string
BindDeletePath string BindDeletePath string
ScriptRunPath string ScriptRunPath string
ScriptCreatePath string ScriptCreatePath string
ScriptListPath string ScriptListPath string
ScriptDeletePath string ScriptDeletePath string
ScriptGetPath string ScriptGetPath string
ScriptUsePath string ScriptUsePath string
ExpListPath string ExpListPath string
ExpGetPath string ExpGetPath string
GrantListPath string ExpGrantListPath string
GrantAddPath string ExpGrantAddPath string
GrantDeletePath string ExpGrantDeletePath string
GrantListPath string
GrantAddPath string
GrantDeletePath string
} }
func InitAPIUrl(c *ApiUrls) *ApiUrls { func InitAPIUrl(c *ApiUrls) *ApiUrls {
@@ -204,6 +210,24 @@ func InitAPIUrl(c *ApiUrls) *ApiUrls {
r.ExpGetPath = expGetPath 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 != "" { if c.GrantListPath != "" {
r.GrantListPath = c.GrantListPath r.GrantListPath = c.GrantListPath
} else { } else {

View File

@@ -143,6 +143,21 @@ func (c *SaasClient) GrantDelete(saasReq *saasapi.SaasReq) (saasRes *saasapi.Saa
return c.post(postUrl, saasReq) 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 {