weldr/upload: no longer reuse the structs from the target package

For serializeation, make our own private structs. The structs
in the target package are not exactly the same as the ones used by
weldr, so in order to avoid too many compromises, let's just do
an explicity translation.

As a general principle, we aim to only use private types for
serialization and rather translate than reuse for different
purposes.

Signed-off-by: Tom Gundersen <teg@jklm.no>
This commit is contained in:
Tom Gundersen 2020-03-21 23:28:00 +01:00
parent 440a5acb41
commit 61836a7079
3 changed files with 69 additions and 61 deletions

View file

@ -1360,7 +1360,7 @@ func (api *API) composeHandler(writer http.ResponseWriter, request *http.Request
ComposeType string `json:"compose_type"`
Size uint64 `json:"size"`
Branch string `json:"branch"`
Upload *UploadRequest `json:"upload"`
Upload *uploadRequest `json:"upload"`
}
type ComposeReply struct {
BuildID uuid.UUID `json:"build_id"`
@ -1396,8 +1396,7 @@ func (api *API) composeHandler(writer http.ResponseWriter, request *http.Request
var uploadTarget *target.Target
if isRequestVersionAtLeast(params, 1) && cr.Upload != nil {
uploadTarget, err = UploadRequestToTarget(*cr.Upload)
uploadTarget, err = uploadRequestToTarget(*cr.Upload)
if err != nil {
errors := responseError{
ID: "UploadError",
@ -1661,7 +1660,7 @@ func (api *API) composeInfoHandler(writer http.ResponseWriter, request *http.Req
ComposeType string `json:"compose_type"`
QueueStatus string `json:"queue_status"`
ImageSize uint64 `json:"image_size"`
Uploads []UploadResponse `json:"uploads,omitempty"`
Uploads []uploadResponse `json:"uploads,omitempty"`
}
reply.ID = id
@ -1676,7 +1675,7 @@ func (api *API) composeInfoHandler(writer http.ResponseWriter, request *http.Req
reply.ImageSize = compose.ImageBuilds[0].Size
if isRequestVersionAtLeast(params, 1) {
reply.Uploads = TargetsToUploadResponses(compose.ImageBuilds[0].Targets)
reply.Uploads = targetsToUploadResponses(compose.ImageBuilds[0].Targets)
}
err = json.NewEncoder(writer).Encode(reply)

View file

@ -1,10 +1,11 @@
package weldr
import (
"sort"
"github.com/google/uuid"
"github.com/osbuild/osbuild-composer/internal/common"
"github.com/osbuild/osbuild-composer/internal/compose"
"sort"
)
type ComposeEntry struct {
@ -17,7 +18,7 @@ type ComposeEntry struct {
JobCreated float64 `json:"job_created"`
JobStarted float64 `json:"job_started,omitempty"`
JobFinished float64 `json:"job_finished,omitempty"`
Uploads []UploadResponse `json:"uploads,omitempty"`
Uploads []uploadResponse `json:"uploads,omitempty"`
}
func composeToComposeEntry(id uuid.UUID, compose compose.Compose, includeUploads bool) *ComposeEntry {
@ -30,7 +31,7 @@ func composeToComposeEntry(id uuid.UUID, compose compose.Compose, includeUploads
composeEntry.QueueStatus = compose.ImageBuilds[0].QueueStatus
if includeUploads {
composeEntry.Uploads = TargetsToUploadResponses(compose.ImageBuilds[0].Targets)
composeEntry.Uploads = targetsToUploadResponses(compose.ImageBuilds[0].Targets)
}
switch compose.ImageBuilds[0].QueueStatus {

View file

@ -11,19 +11,41 @@ import (
"github.com/osbuild/osbuild-composer/internal/target"
)
type UploadResponse struct {
type uploadResponse struct {
Uuid uuid.UUID `json:"uuid"`
Status common.ImageBuildState `json:"status"`
ProviderName string `json:"provider_name"`
ImageName string `json:"image_name"`
CreationTime float64 `json:"creation_time"`
Settings target.TargetOptions `json:"settings"`
Settings uploadSettings `json:"settings"`
}
type UploadRequest struct {
Provider string `json:"provider"`
ImageName string `json:"image_name"`
Settings target.TargetOptions `json:"settings"`
type uploadSettings interface {
isUploadSettings()
}
type awsUploadSettings struct {
Region string `json:"region"`
AccessKeyID string `json:"accessKeyID"`
SecretAccessKey string `json:"secretAccessKey"`
Bucket string `json:"bucket"`
Key string `json:"key"`
}
func (awsUploadSettings) isUploadSettings() {}
type azureUploadSettings struct {
Account string `json:"account"`
AccessKey string `json:"accessKey"`
Container string `json:"container"`
}
func (azureUploadSettings) isUploadSettings() {}
type uploadRequest struct {
Provider string `json:"provider"`
ImageName string `json:"image_name"`
Settings uploadSettings `json:"settings"`
}
type rawUploadRequest struct {
@ -32,95 +54,80 @@ type rawUploadRequest struct {
Settings json.RawMessage `json:"settings"`
}
func (u *UploadRequest) UnmarshalJSON(data []byte) error {
var rawUpload rawUploadRequest
err := json.Unmarshal(data, &rawUpload)
func (u *uploadRequest) UnmarshalJSON(data []byte) error {
var rawUploadRequest rawUploadRequest
err := json.Unmarshal(data, &rawUploadRequest)
if err != nil {
return err
}
// we need to convert provider name to target name to use the unmarshaller
targetName := providerNameToTargetNameMap[rawUpload.Provider]
options, err := target.UnmarshalTargetOptions(targetName, rawUpload.Settings)
var settings uploadSettings
switch rawUploadRequest.Provider {
case "azure":
settings = new(azureUploadSettings)
case "aws":
settings = new(awsUploadSettings)
default:
return errors.New("unexpected provider name")
}
err = json.Unmarshal(rawUploadRequest.Settings, settings)
if err != nil {
return err
}
u.Provider = rawUpload.Provider
u.ImageName = rawUpload.ImageName
u.Settings = options
u.Provider = rawUploadRequest.Provider
u.ImageName = rawUploadRequest.ImageName
u.Settings = settings
return err
}
var targetNameToProviderNameMap = map[string]string{
"org.osbuild.aws": "aws",
"org.osbuild.azure": "azure",
}
var providerNameToTargetNameMap = map[string]string{
"aws": "org.osbuild.aws",
"azure": "org.osbuild.azure",
}
func TargetsToUploadResponses(targets []*target.Target) []UploadResponse {
var uploads []UploadResponse
func targetsToUploadResponses(targets []*target.Target) []uploadResponse {
var uploads []uploadResponse
for _, t := range targets {
if t.Name == "org.osbuild.local" {
continue
}
providerName, providerExist := targetNameToProviderNameMap[t.Name]
if !providerExist {
panic("target name " + t.Name + " is not defined in conversion map!")
}
upload := UploadResponse{
upload := uploadResponse{
Uuid: t.Uuid,
Status: t.Status,
ProviderName: providerName,
ImageName: t.ImageName,
CreationTime: float64(t.Created.UnixNano()) / 1000000000,
}
switch options := t.Options.(type) {
case *target.LocalTargetOptions:
continue
case *target.AWSTargetOptions:
upload.Settings = &target.AWSTargetOptions{
upload.ProviderName = "aws"
upload.Settings = &awsUploadSettings{
Region: options.Region,
AccessKeyID: options.AccessKeyID,
SecretAccessKey: options.SecretAccessKey,
Bucket: options.Bucket,
Key: options.Key,
}
uploads = append(uploads, upload)
case *target.AzureTargetOptions:
upload.Settings = &target.AzureTargetOptions{
upload.ProviderName = "azure"
upload.Settings = &azureUploadSettings{
Account: options.Account,
AccessKey: options.AccessKey,
Container: options.Container,
}
uploads = append(uploads, upload)
}
uploads = append(uploads, upload)
}
return uploads
}
func UploadRequestToTarget(u UploadRequest) (*target.Target, error) {
func uploadRequestToTarget(u uploadRequest) (*target.Target, error) {
var t target.Target
targetName, targetExist := providerNameToTargetNameMap[u.Provider]
if !targetExist {
return nil, errors.New("Unknown provider name " + u.Provider)
}
t.Uuid = uuid.New()
t.ImageName = u.ImageName
t.Name = targetName
t.Status = common.IBWaiting
t.Created = time.Now()
switch options := u.Settings.(type) {
case *target.LocalTargetOptions:
t.Options = &target.LocalTargetOptions{}
case *target.AWSTargetOptions:
case *awsUploadSettings:
t.Name = "org.osbuild.aws"
t.Options = &target.AWSTargetOptions{
Region: options.Region,
AccessKeyID: options.AccessKeyID,
@ -128,7 +135,8 @@ func UploadRequestToTarget(u UploadRequest) (*target.Target, error) {
Bucket: options.Bucket,
Key: options.Key,
}
case *target.AzureTargetOptions:
case *azureUploadSettings:
t.Name = "org.osbuild.azure"
t.Options = &target.AzureTargetOptions{
Account: options.Account,
AccessKey: options.AccessKey,