weldr: add support for toml blueprints

This commit is contained in:
Lars Karlitski 2019-12-03 00:53:44 +01:00 committed by Tom Gundersen
parent bddac13048
commit 20bb60f3fd
4 changed files with 118 additions and 9 deletions

1
go.mod
View file

@ -4,6 +4,7 @@ go 1.12
require (
github.com/Azure/azure-storage-blob-go v0.8.0
github.com/BurntSushi/toml v0.3.1
github.com/aws/aws-sdk-go v1.25.37
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f
github.com/gobwas/glob v0.2.3

2
go.sum
View file

@ -2,6 +2,8 @@ github.com/Azure/azure-pipeline-go v0.2.1 h1:OLBdZJ3yvOn2MezlWvbrBMTEUQC72zAftRZ
github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4=
github.com/Azure/azure-storage-blob-go v0.8.0 h1:53qhf0Oxa0nOjgbDeeYPUeyiNmafAFEY95rZLK0Tj6o=
github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/aws/aws-sdk-go v1.25.37 h1:gBtB/F3dophWpsUQKN/Kni+JzYEH2mGHF4hWNtfED1w=
github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c=

View file

@ -2,15 +2,18 @@ package weldr
import (
"encoding/json"
"errors"
"fmt"
"io"
"log"
"net"
"net/http"
"net/url"
"sort"
"strconv"
"strings"
"github.com/BurntSushi/toml"
"github.com/google/uuid"
"github.com/julienschmidt/httprouter"
@ -701,11 +704,44 @@ func (api *API) blueprintsInfoHandler(writer http.ResponseWriter, request *http.
changes = append(changes, change{changed, blueprint.Name})
}
json.NewEncoder(writer).Encode(reply{
Blueprints: blueprints,
Changes: changes,
Errors: []responseError{},
})
q, err := url.ParseQuery(request.URL.RawQuery)
if err != nil {
errors := responseError{
ID: "InvalidChars",
Msg: fmt.Sprintf("invalid query string: %v", err),
}
statusResponseError(writer, http.StatusBadRequest, errors)
return
}
format := q.Get("format")
if format == "json" || format == "" {
json.NewEncoder(writer).Encode(reply{
Blueprints: blueprints,
Changes: changes,
Errors: []responseError{},
})
} else if format == "toml" {
// lorax concatenates multiple blueprints with `\n\n` here,
// which is never useful. Deviate by only returning the first
// blueprint.
if len(blueprints) > 1 {
errors := responseError{
ID: "HTTPError",
Msg: "toml format only supported when requesting one blueprint",
}
statusResponseError(writer, http.StatusBadRequest, errors)
return
}
toml.NewEncoder(writer).Encode(blueprints[0])
} else {
errors := responseError{
ID: "InvalidChars",
Msg: fmt.Sprintf("invalid `format` parameter: %s", format),
}
statusResponseError(writer, http.StatusBadRequest, errors)
return
}
}
func (api *API) blueprintsDepsolveHandler(writer http.ResponseWriter, request *http.Request, params httprouter.Params) {
@ -1030,21 +1066,29 @@ func (api *API) blueprintsNewHandler(writer http.ResponseWriter, request *http.R
}
contentType := request.Header["Content-Type"]
if len(contentType) != 1 || contentType[0] != "application/json" {
if len(contentType) != 1 {
errors := responseError{
ID: "BlueprintsError",
Msg: "'blueprint must be json'",
Msg: "missing Content-Type header",
}
statusResponseError(writer, http.StatusBadRequest, errors)
return
}
var blueprint blueprint.Blueprint
err := json.NewDecoder(request.Body).Decode(&blueprint)
var err error
if contentType[0] == "application/json" {
err = json.NewDecoder(request.Body).Decode(&blueprint)
} else if contentType[0] == "text/x-toml" {
_, err = toml.DecodeReader(request.Body, &blueprint)
} else {
err = errors.New("blueprint must be in json or toml format")
}
if err != nil {
errors := responseError{
ID: "BlueprintsError",
Msg: "400 Bad Request: The browser (or proxy) sent a request that this server could not understand.",
Msg: "400 Bad Request: The browser (or proxy) sent a request that this server could not understand: " + err.Error(),
}
statusResponseError(writer, http.StatusBadRequest, errors)
return

View file

@ -1,8 +1,10 @@
package weldr_test
import (
"bytes"
"math/rand"
"net/http"
"net/http/httptest"
"os"
"strconv"
"testing"
@ -17,6 +19,7 @@ import (
"github.com/osbuild/osbuild-composer/internal/test"
"github.com/osbuild/osbuild-composer/internal/weldr"
"github.com/BurntSushi/toml"
"github.com/google/go-cmp/cmp"
)
@ -72,6 +75,29 @@ func TestBlueprintsNew(t *testing.T) {
}
}
func TestBlueprintsNewToml(t *testing.T) {
blueprint := `
name = "test"
description = "Test"
version = "0.0.0"
[[packages]]
name = "httpd"
version = "2.4.*"`
req := httptest.NewRequest("POST", "/api/v0/blueprints/new", bytes.NewReader([]byte(blueprint)))
req.Header.Set("Content-Type", "text/x-toml")
recorder := httptest.NewRecorder()
api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
api.ServeHTTP(recorder, req)
r := recorder.Result()
if r.StatusCode != http.StatusOK {
t.Fatalf("unexpected status %v", r.StatusCode)
}
}
func TestBlueprintsWorkspace(t *testing.T) {
var cases = []struct {
Method string
@ -115,6 +141,42 @@ func TestBlueprintsInfo(t *testing.T) {
}
}
func TestBlueprintsInfoToml(t *testing.T) {
api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
test.SendHTTP(api, true, "POST", "/api/v0/blueprints/new", `{"name":"test1","description":"Test","packages":[{"name":"httpd","version":"2.4.*"}],"version":"0.0.0"}`)
req := httptest.NewRequest("GET", "/api/v0/blueprints/info/test1?format=toml", nil)
recorder := httptest.NewRecorder()
api.ServeHTTP(recorder, req)
resp := recorder.Result()
if resp.StatusCode != http.StatusOK {
t.Fatalf("unexpected status %v", resp.StatusCode)
}
var got blueprint.Blueprint
_, err := toml.DecodeReader(resp.Body, &got)
if err != nil {
t.Fatalf("error decoding toml file: %v", err)
}
t.Logf("%v", got)
expected := blueprint.Blueprint{
Name: "test1",
Description: "Test",
Version: "0.0.0",
Packages: []blueprint.Package{
{ "httpd", "2.4.*" },
},
Groups: []blueprint.Group{},
Modules: []blueprint.Package{},
}
if diff := cmp.Diff(got, expected); diff != "" {
t.Fatalf("received unexpected blueprint: %s", diff)
}
}
func TestBlueprintsFreeze(t *testing.T) {
var cases = []struct {
Fixture rpmmd_mock.FixtureGenerator