autogits/bots-common/obs_utils.go

252 lines
5.2 KiB
Go
Raw Normal View History

2024-07-21 22:15:11 +02:00
package common
import (
2024-07-26 16:53:09 +02:00
"bytes"
2024-07-21 22:15:11 +02:00
"encoding/xml"
"fmt"
"io"
"log"
"net/http"
"net/url"
)
type ObsClient struct {
baseUrl *url.URL
client *http.Client
user, password string
cookie string
2024-07-22 17:35:48 +02:00
HomeProject string
2024-07-21 22:15:11 +02:00
}
2024-07-22 17:09:45 +02:00
func NewObsClient(host string) (*ObsClient, error) {
2024-07-21 22:15:11 +02:00
baseUrl, err := url.Parse("https://" + host)
if err != nil {
return nil, err
}
return &ObsClient{
baseUrl: baseUrl,
client: &http.Client{},
2024-07-22 17:09:45 +02:00
user: obsUser,
password: obsPassword,
2024-07-22 17:35:48 +02:00
HomeProject: fmt.Sprintf("home:%s", obsUser),
2024-07-21 22:15:11 +02:00
}, nil
}
2024-07-26 16:53:09 +02:00
type RepositoryPathMeta struct {
Project string `xml:"project,attr"`
Repository string `xml:"repository,attr"`
}
2024-07-21 22:15:11 +02:00
type RepositoryMeta struct {
2024-07-26 16:53:09 +02:00
Name string `xml:"name,attr"`
Archs []string `xml:"arch"`
Paths []RepositoryPathMeta `xml:"path"`
2024-07-21 22:15:11 +02:00
}
2024-07-22 17:09:45 +02:00
type Flags struct {
Contents string `xml:",innerxml"`
}
2024-07-21 22:15:11 +02:00
type ProjectMeta struct {
2024-07-26 16:53:09 +02:00
XMLName xml.Name `xml:"project"`
Name string `xml:"name,attr"`
Title string `xml:"title"`
Description string `xml:"description"`
ScmSync string `xml:"scmsync"`
Repositories []RepositoryMeta `xml:"repository"`
2024-07-22 17:09:45 +02:00
BuildFlags Flags `xml:"build"`
PublicFlags Flags `xml:"publish"`
2024-07-26 16:53:09 +02:00
DebugFlags Flags `xml:"debuginfo"`
UseForBuild Flags `xml:"useforbuild"`
2024-07-21 22:15:11 +02:00
}
func parseProjectMeta(data []byte) (*ProjectMeta, error) {
var meta ProjectMeta
err := xml.Unmarshal(data, &meta)
if err != nil {
return nil, err
}
return &meta, nil
}
func (c *ObsClient) GetProjectMeta(project string) (*ProjectMeta, error) {
req, err := http.NewRequest("GET", c.baseUrl.JoinPath("source", project, "_meta").String(), nil)
if err != nil {
return nil, err
}
req.SetBasicAuth(c.user, c.password)
2024-07-26 16:53:09 +02:00
log.Printf("request: %#v", *req.URL)
log.Printf("headers: %#v", req.Header)
2024-07-21 22:15:11 +02:00
res, err := c.client.Do(req)
if err != nil {
return nil, err
}
switch res.StatusCode {
case 200:
break
case 404:
return nil, nil
default:
return nil, fmt.Errorf("Unexpected return code: %d", res.StatusCode)
}
data, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}
return parseProjectMeta(data)
}
2024-07-26 16:53:09 +02:00
func ObsSafeProjectName(prjname string) string {
if len(prjname) < 1 {
return prjname
} else if len(prjname) > 200 {
prjname = prjname[:199]
}
switch prjname[0] {
case '_', '.', ':':
prjname = "X" + prjname[1:]
// no UTF-8 in OBS :(
// prjname = "_" + prjname[1:]
// case ':':
// prjname = "" + prjname[1:]
// case '.':
// prjname = "" + prjname[1:]
}
return prjname
}
func (c *ObsClient) SetProjectMeta(meta *ProjectMeta) (error) {
req, err := http.NewRequest("PUT", c.baseUrl.JoinPath("source", meta.Name, "_meta").String(), nil)
if err != nil {
return err
}
req.SetBasicAuth(c.user, c.password)
xml, err := xml.Marshal(meta)
if err != nil {
return err
}
req.Body = io.NopCloser(bytes.NewReader(xml))
log.Printf("headers: %#v", req.Header)
log.Printf("xml: %s", xml)
res, err := c.client.Do(req)
if err != nil {
return err
}
switch res.StatusCode {
case 200:
break
default:
return fmt.Errorf("Unexpected return code: %d", res.StatusCode)
}
return nil
}
2024-07-21 22:15:11 +02:00
func (c *ObsClient) DeleteProject(project string) error {
req, err := http.NewRequest("DELETE", c.baseUrl.JoinPath("source", project).String(), nil)
if err != nil {
return err
}
req.SetBasicAuth(c.user, c.password)
res, err := c.client.Do(req)
if err != nil {
return err
}
if res.StatusCode != 200 {
return fmt.Errorf("Unexpected return code: %d", res.StatusCode)
}
return nil
}
type BuildStatus struct {
Package string `xml:"package,attr"`
Code string `xml:"code,attr"`
Details string `xml:"details"`
}
type BuildResult struct {
Project string `xml:"project,attr"`
Repository string `xml:"repository,attr"`
Arch string `xml:"arch,attr"`
Code string `xml:"code,attr"`
Status []BuildStatus `xml:"status"`
Binaries []BinaryList `xml:"binarylist"`
}
type Binary struct {
Size uint64 `xml:"size,attr"`
Filename string `xml:"filename,attr"`
Mtime uint64 `xml:"mtime,attr"`
}
type BinaryList struct {
Package string `xml:"package,attr"`
Binary []Binary `xml:"binary"`
}
type BuildResultList struct {
XMLName xml.Name `xml:"resultlist"`
Result []BuildResult `xml:"result"`
}
func parseBuildResults(data []byte) (*BuildResultList, error) {
result := BuildResultList{}
err := xml.Unmarshal(data, &result)
if err != nil {
return nil, err
}
return &result, nil
}
func (c *ObsClient) BuildStatus(project string) (*BuildResultList, error) {
u := c.baseUrl.JoinPath("build", project, "_result")
query := u.Query()
query.Add("view", "status")
query.Add("view", "binarylist")
query.Add("multibuild", "1")
u.RawQuery = query.Encode()
req, err := http.NewRequest("GET", u.String(), nil)
log.Print(u.String())
if err != nil {
return nil, err
}
req.SetBasicAuth(c.user, c.password)
res, err := c.client.Do(req)
if err != nil {
return nil, err
}
if res.StatusCode != 200 {
return nil, fmt.Errorf("Unexpected return code: %d", res.StatusCode)
}
data, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}
return parseBuildResults(data)
}