api: implement /compose/logs route
The implementation is just a stub returning always the same tar archive. The ability to return actual logs will be implemented in the future - osbuild isn't currently returning any logs.
This commit is contained in:
parent
d7f81b36e6
commit
4e62f181fa
2 changed files with 124 additions and 0 deletions
|
|
@ -1,6 +1,7 @@
|
|||
package weldr
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
|
@ -92,6 +93,7 @@ func New(rpmmd rpmmd.RPMMD, distro distro.Distro, logger *log.Logger, store *sto
|
|||
api.router.GET("/api/v:version/compose/finished", api.composeFinishedHandler)
|
||||
api.router.GET("/api/v:version/compose/failed", api.composeFailedHandler)
|
||||
api.router.GET("/api/v:version/compose/image/:uuid", api.composeImageHandler)
|
||||
api.router.GET("/api/v:version/compose/logs/:uuid", api.composeLogsHandler)
|
||||
api.router.POST("/api/v:version/compose/uploads/schedule/:uuid", api.uploadsScheduleHandler)
|
||||
|
||||
api.router.DELETE("/api/v:version/upload/delete/:uuid", api.uploadsDeleteHandler)
|
||||
|
|
@ -1463,6 +1465,59 @@ func (api *API) composeImageHandler(writer http.ResponseWriter, request *http.Re
|
|||
io.Copy(writer, file)
|
||||
}
|
||||
|
||||
func (api *API) composeLogsHandler(writer http.ResponseWriter, request *http.Request, params httprouter.Params) {
|
||||
if !verifyRequestVersion(writer, params, 0) {
|
||||
return
|
||||
}
|
||||
|
||||
uuidString := params.ByName("uuid")
|
||||
id, err := uuid.Parse(uuidString)
|
||||
if err != nil {
|
||||
errors := responseError{
|
||||
ID: "UnknownUUID",
|
||||
Msg: fmt.Sprintf("%s is not a valid build uuid", uuidString),
|
||||
}
|
||||
statusResponseError(writer, http.StatusBadRequest, errors)
|
||||
return
|
||||
}
|
||||
|
||||
compose, exists := api.store.GetCompose(id)
|
||||
if !exists {
|
||||
errors := responseError{
|
||||
ID: "UnknownUUID",
|
||||
Msg: fmt.Sprintf("Compose %s doesn't exist", uuidString),
|
||||
}
|
||||
statusResponseError(writer, http.StatusBadRequest, errors)
|
||||
return
|
||||
}
|
||||
|
||||
if compose.QueueStatus != "FINISHED" && compose.QueueStatus != "FAILED" {
|
||||
errors := responseError{
|
||||
ID: "BuildInWrongState",
|
||||
Msg: fmt.Sprintf("Build %s not in FINISHED or FAILED state.", uuidString),
|
||||
}
|
||||
statusResponseError(writer, http.StatusBadRequest, errors)
|
||||
return
|
||||
}
|
||||
|
||||
writer.Header().Set("Content-Disposition", "attachment; filename="+id.String()+"-logs.tar")
|
||||
writer.Header().Set("Content-Type", "application/x-tar")
|
||||
|
||||
tw := tar.NewWriter(writer)
|
||||
|
||||
// TODO: return real log from osbuild
|
||||
fileContents := []byte("SUCCESS\n")
|
||||
|
||||
header := &tar.Header{
|
||||
Name: "logs/osbuild.log",
|
||||
Mode: 0644,
|
||||
Size: int64(len(fileContents)),
|
||||
}
|
||||
|
||||
tw.WriteHeader(header)
|
||||
tw.Write(fileContents)
|
||||
}
|
||||
|
||||
func (api *API) composeFinishedHandler(writer http.ResponseWriter, request *http.Request, params httprouter.Params) {
|
||||
if !verifyRequestVersion(writer, params, 0) {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package weldr_test
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
|
|
@ -389,6 +391,73 @@ func TestComposeInfo(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestComposeLogs(t *testing.T) {
|
||||
if len(os.Getenv("OSBUILD_COMPOSER_TEST_EXTERNAL")) > 0 {
|
||||
t.Skip("This test is for internal testing only")
|
||||
}
|
||||
|
||||
var successCases = []struct {
|
||||
Path string
|
||||
ExpectedContentDisposition string
|
||||
ExpectedContentType string
|
||||
ExpectedFileName string
|
||||
ExpectedFileContent string
|
||||
}{
|
||||
{"/api/v0/compose/logs/30000000-0000-0000-0000-000000000002", "attachment; filename=30000000-0000-0000-0000-000000000002-logs.tar", "application/x-tar", "logs/osbuild.log", "SUCCESS\n"},
|
||||
{"/api/v1/compose/logs/30000000-0000-0000-0000-000000000002", "attachment; filename=30000000-0000-0000-0000-000000000002-logs.tar", "application/x-tar", "logs/osbuild.log", "SUCCESS\n"},
|
||||
}
|
||||
|
||||
for _, c := range successCases {
|
||||
api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
|
||||
|
||||
response := test.SendHTTP(api, false, "GET", c.Path, "")
|
||||
if response.Header.Get("content-disposition") != c.ExpectedContentDisposition {
|
||||
t.Errorf("%s: expected content-disposition: %s, but got: %s", c.Path, c.ExpectedContentDisposition, response.Header.Get("content-disposition"))
|
||||
}
|
||||
|
||||
if response.Header.Get("content-type") != c.ExpectedContentType {
|
||||
t.Errorf("%s: expected content-type: %s, but got: %s", c.Path, c.ExpectedContentType, response.Header.Get("content-type"))
|
||||
}
|
||||
|
||||
tr := tar.NewReader(response.Body)
|
||||
h, err := tr.Next()
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("untarring failed with error: %s", err.Error())
|
||||
}
|
||||
|
||||
if h.Name != c.ExpectedFileName {
|
||||
t.Errorf("%s: expected log content: %s, but got: %s", c.Path, c.ExpectedFileName, h.Name)
|
||||
}
|
||||
|
||||
var buffer bytes.Buffer
|
||||
|
||||
io.Copy(&buffer, tr)
|
||||
|
||||
if buffer.String() != c.ExpectedFileContent {
|
||||
t.Errorf("%s: expected log content: %s, but got: %s", c.Path, c.ExpectedFileContent, buffer.String())
|
||||
}
|
||||
}
|
||||
|
||||
var failureCases = []struct {
|
||||
Path string
|
||||
ExpectedJSON string
|
||||
}{
|
||||
{"/api/v1/compose/logs/30000000-0000-0000-0000", `{"status":false,"errors":[{"id":"UnknownUUID","msg":"30000000-0000-0000-0000 is not a valid build uuid"}]}`},
|
||||
{"/api/v1/compose/logs/42000000-0000-0000-0000-000000000000", `{"status":false,"errors":[{"id":"UnknownUUID","msg":"Compose 42000000-0000-0000-0000-000000000000 doesn't exist"}]}`},
|
||||
{"/api/v1/compose/logs/30000000-0000-0000-0000-000000000000", `{"status":false,"errors":[{"id":"BuildInWrongState","msg":"Build 30000000-0000-0000-0000-000000000000 not in FINISHED or FAILED state."}]}`},
|
||||
}
|
||||
|
||||
if len(os.Getenv("OSBUILD_COMPOSER_TEST_EXTERNAL")) > 0 {
|
||||
t.Skip("This test is for internal testing only")
|
||||
}
|
||||
|
||||
for _, c := range failureCases {
|
||||
api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
|
||||
test.TestRoute(t, api, false, "GET", c.Path, "", http.StatusBadRequest, c.ExpectedJSON)
|
||||
}
|
||||
}
|
||||
|
||||
func TestComposeQueue(t *testing.T) {
|
||||
var cases = []struct {
|
||||
Fixture rpmmd_mock.FixtureGenerator
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue