diff options
| author | Denys Fedoryshchenko <denys.f@collabora.com> | 2025-06-30 17:15:48 +0300 |
|---|---|---|
| committer | Aleksandr Nogikh <nogikh@google.com> | 2025-10-06 08:29:13 +0000 |
| commit | fd070483688b68ab7c0fef4bfbf2cdc2defd5f63 (patch) | |
| tree | a162020d38528c1d6f19f3aeec1a71eefcc6673a | |
| parent | dfce4a517db03fbd9bd29560bfb17b7ecfeccda2 (diff) | |
kcidb: convert from Google PubSub to plain REST interface
KCIDB removing Google PubSub and start to accept REST submissions.
This will require new configuration options, such as REST URL and
token.
Signed-off-by: Denys Fedoryshchenko <denys.f@collabora.com>
| -rw-r--r-- | dashboard/app/config.go | 25 | ||||
| -rw-r--r-- | dashboard/app/kcidb.go | 2 | ||||
| -rw-r--r-- | pkg/kcidb/client.go | 62 | ||||
| -rw-r--r-- | tools/syz-kcidb/kcidb.go | 10 |
4 files changed, 56 insertions, 43 deletions
diff --git a/dashboard/app/config.go b/dashboard/app/config.go index 8c9d9fb6e..7f9885fd9 100644 --- a/dashboard/app/config.go +++ b/dashboard/app/config.go @@ -4,11 +4,11 @@ package main import ( - "bytes" "context" "encoding/json" "fmt" "net/mail" + "net/url" "regexp" "strings" "time" @@ -366,12 +366,10 @@ type CCConfig struct { type KcidbConfig struct { // Origin is how this system identified in Kcidb, e.g. "syzbot_foobar". Origin string - // Project is Kcidb GCE project name, e.g. "kernelci-production". - Project string - // Topic is pubsub topic to publish messages to, e.g. "playground_kernelci_new". - Topic string - // Credentials is Google application credentials file contents to use for authorization. - Credentials []byte + // RestURI is the REST API endpoint to which the Kcidb client will send data. + RestURI string + // Token is the authorization token to use for the Kcidb client. + Token string } // ThrottleConfig determines how many requests a single client can make in a period of time. @@ -813,14 +811,15 @@ func checkKcidb(ns string, kcidb *KcidbConfig) { if !regexp.MustCompile("^[a-z0-9_]+$").MatchString(kcidb.Origin) { panic(fmt.Sprintf("%v: bad Kcidb origin %q", ns, kcidb.Origin)) } - if kcidb.Project == "" { - panic(fmt.Sprintf("%v: empty Kcidb project", ns)) + if kcidb.RestURI == "" { + panic(fmt.Sprintf("%v: empty Kcidb RestURI", ns)) } - if kcidb.Topic == "" { - panic(fmt.Sprintf("%v: empty Kcidb topic", ns)) + // Validate RestURI must be a valid URL. + if _, err := url.ParseRequestURI(kcidb.RestURI); err != nil { + panic(fmt.Sprintf("%v: invalid Kcidb RestURI %q: %v", ns, kcidb.RestURI, err)) } - if !bytes.Contains(kcidb.Credentials, []byte("private_key")) { - panic(fmt.Sprintf("%v: empty Kcidb credentials", ns)) + if kcidb.Token == "" || len(kcidb.Token) < 8 { + panic(fmt.Sprintf("%v: bad Kcidb token %q", ns, kcidb.Token)) } } diff --git a/dashboard/app/kcidb.go b/dashboard/app/kcidb.go index f2cfeaacb..25ec23424 100644 --- a/dashboard/app/kcidb.go +++ b/dashboard/app/kcidb.go @@ -32,7 +32,7 @@ func handleKcidbPoll(w http.ResponseWriter, r *http.Request) { } func handleKcidbNamespce(c context.Context, ns string, cfg *KcidbConfig) error { - client, err := kcidb.NewClient(c, cfg.Origin, cfg.Project, cfg.Topic, cfg.Credentials) + client, err := kcidb.NewClient(c, cfg.Origin, cfg.RestURI, cfg.Token) if err != nil { return err } diff --git a/pkg/kcidb/client.go b/pkg/kcidb/client.go index c733aa910..bba811c7e 100644 --- a/pkg/kcidb/client.go +++ b/pkg/kcidb/client.go @@ -8,22 +8,21 @@ import ( "context" "encoding/json" "fmt" + "net/http" "os" "os/exec" "strings" "time" - "cloud.google.com/go/pubsub" "github.com/google/syzkaller/dashboard/dashapi" "github.com/google/syzkaller/sys/targets" - "google.golang.org/api/option" ) type Client struct { - ctx context.Context - origin string - client *pubsub.Client - topic *pubsub.Topic + ctx context.Context + origin string + resturi string + token string } // NewClient creates a new client to send pubsub messages to Kcidb. @@ -31,23 +30,40 @@ type Client struct { // Project is Kcidb GCE project name, e.g. "kernelci-production". // Topic is pubsub topic to publish messages to, e.g. "playground_kernelci_new". // Credentials is Google application credentials file contents to use for authorization. -func NewClient(ctx context.Context, origin, project, topic string, credentials []byte) (*Client, error) { - client, err := pubsub.NewClient(ctx, project, option.WithCredentialsJSON(credentials)) - if err != nil { - return nil, err - } +func NewClient(ctx context.Context, origin, resturi, token string) (*Client, error) { c := &Client{ - ctx: ctx, - origin: origin, - client: client, - topic: client.Topic(topic), + ctx: ctx, + origin: origin, + resturi: resturi, + token: token, } - return c, err + return c, nil } func (c *Client) Close() error { - c.topic.Stop() - return c.client.Close() + return nil +} + +func (c *Client) RESTSubmit(data []byte) error { + if c.resturi == "" { + return fmt.Errorf("resturi is not set") + } + req, err := http.NewRequest("POST", c.resturi, bytes.NewReader(data)) + if err != nil { + return fmt.Errorf("failed to create request: %w", err) + } + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Authorization", "Bearer "+c.token) + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return fmt.Errorf("failed to send request: %w", err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("unexpected response status: %s", resp.Status) + } + return nil } func (c *Client) Publish(bug *dashapi.BugReport) error { @@ -62,7 +78,9 @@ func (c *Client) Publish(bug *dashapi.BugReport) error { if err := kcidbValidate(data); err != nil { return err } - _, err = c.topic.Publish(c.ctx, &pubsub.Message{Data: data}).Get(c.ctx) + if err := c.RESTSubmit(data); err != nil { + return fmt.Errorf("failed to submit kcidb json: %w", err) + } return err } @@ -100,8 +118,8 @@ func (c *Client) convert(target *targets.Target, bug *dashapi.BugReport) *Kcidb GitRepositoryURL: normalizeRepo(bug.KernelRepo), GitCommitHash: bug.KernelCommit, GitRepositoryBranch: bug.KernelBranch, - Comment: bug.KernelCommitTitle, - StartTime: bug.BuildTime.Format(time.RFC3339), + Comment: bug.KernelCommitTitle, + StartTime: bug.BuildTime.Format(time.RFC3339), Valid: true, }, }, @@ -155,7 +173,7 @@ func (c *Client) convert(target *targets.Target, bug *dashapi.BugReport) *Kcidb Path: "syzkaller", StartTime: bug.CrashTime.Format(time.RFC3339), OutputFiles: outputFiles, - Comment: bug.Title, + Comment: bug.Title, Status: "FAIL", Misc: &TestMisc{ OriginURL: bug.Link, diff --git a/tools/syz-kcidb/kcidb.go b/tools/syz-kcidb/kcidb.go index 81504c654..8d1255cce 100644 --- a/tools/syz-kcidb/kcidb.go +++ b/tools/syz-kcidb/kcidb.go @@ -6,7 +6,6 @@ package main import ( "context" "flag" - "os" "github.com/google/syzkaller/dashboard/dashapi" "github.com/google/syzkaller/pkg/kcidb" @@ -20,7 +19,8 @@ func main() { topicName = "playground_kernelci_new" ) var ( - flagCred = flag.String("cred", "", "application credentials file for KCIDB") + flagRestURI = flag.String("rest", "", "REST API endpoint for KCIDB") + flagToken = flag.String("token", "", "KCIDB API token") flagDashClient = flag.String("client", "", "dashboard client") flagDashAddr = flag.String("addr", "", "dashboard address") flagDashKey = flag.String("key", "", "dashboard API key") @@ -37,12 +37,8 @@ func main() { tool.Fail(err) } - cred, err := os.ReadFile(*flagCred) - if err != nil { - tool.Fail(err) - } kcidb.Validate = true - client, err := kcidb.NewClient(context.Background(), origin, projectID, topicName, cred) + client, err := kcidb.NewClient(context.Background(), origin, *flagRestURI, *flagToken) if err != nil { tool.Fail(err) } |
