From 2860398c2a5c19aeb825fbd40003bda9d41ca2f8 Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Thu, 9 Apr 2020 13:49:06 -0700 Subject: [PATCH] store, weldr: Add support for fake composes Yes. This goes against my desire not to change code to accommodate tests. But there is no other good way to test compose results without long running, and possibly fragile, composes. And this matches lorax's behavior. The change adds support for the ?test=1|2 query parameter to the compose POST, and a new store function - PushTestCompose that handles creating the fake compose results. Passing ?test=1 will create a failed compose. Passing ?test=2 will create a successful compose, but one without any files. The purpose of these is to be able to test the compose result API responses like compose/failed, etc. --- internal/store/store.go | 67 +++++++++++++++++++++++++++++++++++++++++ internal/weldr/api.go | 24 ++++++++++++++- 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/internal/store/store.go b/internal/store/store.go index 3dc43aca2..66b7d90b9 100644 --- a/internal/store/store.go +++ b/internal/store/store.go @@ -554,6 +554,73 @@ func (s *Store) PushCompose(imageType distro.ImageType, bp *blueprint.Blueprint, return composeID, nil } +// PushTestCompose is used for testing +// Set testSuccess to create a fake successful compose, otherwise it will create a failed compose +// It does not actually run a compose job +func (s *Store) PushTestCompose(imageType distro.ImageType, bp *blueprint.Blueprint, repos []rpmmd.RepoConfig, packages, buildPackages []rpmmd.PackageSpec, size uint64, targets []*target.Target, testSuccess bool) (uuid.UUID, error) { + if targets == nil { + targets = []*target.Target{} + } + + composeID := uuid.New() + + // Compatibility layer for image types in Weldr API v0 + imageTypeCommon, exists := common.ImageTypeFromCompatString(imageType.Name()) + if !exists { + panic("fatal error, compose type does not exist") + } + + if s.stateDir != nil { + outputDir := s.getImageBuildDirectory(composeID, 0) + + err := os.MkdirAll(outputDir, 0755) + if err != nil { + return uuid.Nil, fmt.Errorf("cannot create output directory for job %v: %#v", composeID, err) + } + } + + manifestStruct, err := imageType.Manifest(bp.Customizations, repos, packages, buildPackages, imageType.Size(size)) + if err != nil { + return uuid.Nil, err + } + // FIXME: handle or comment this possible error + _ = s.change(func() error { + s.Composes[composeID] = compose.Compose{ + Blueprint: bp, + ImageBuilds: []compose.ImageBuild{ + { + QueueStatus: common.IBRunning, + Manifest: manifestStruct, + ImageType: imageTypeCommon, + Targets: targets, + JobCreated: time.Now(), + JobStarted: time.Now(), + Size: size, + }, + }, + } + return nil + }) + + var status common.ImageBuildState + var result common.ComposeResult + if testSuccess { + status = common.IBFinished + result = common.ComposeResult{Success: true} + } else { + status = common.IBFailed + result = common.ComposeResult{} + } + + // Instead of starting the job, immediately set a final status + err = s.UpdateImageBuildInCompose(composeID, 0, status, &result) + if err != nil { + return uuid.Nil, err + } + + return composeID, nil +} + // DeleteCompose deletes the compose from the state file and also removes all files on disk that are // associated with this compose func (s *Store) DeleteCompose(id uuid.UUID) error { diff --git a/internal/weldr/api.go b/internal/weldr/api.go index 93a5e831c..b1c0d3e98 100644 --- a/internal/weldr/api.go +++ b/internal/weldr/api.go @@ -1467,7 +1467,29 @@ func (api *API) composeHandler(writer http.ResponseWriter, request *http.Request return } - composeID, err := api.store.PushCompose(imageType, bp, api.allRepositories(), packages, buildPackages, cr.Size, targets) + var composeID uuid.UUID + + // Check for test parameter + 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 + } + + testMode := q.Get("test") + if testMode == "1" { + // Create a failed compose + composeID, err = api.store.PushTestCompose(imageType, bp, api.allRepositories(), packages, buildPackages, cr.Size, targets, false) + } else if testMode == "2" { + // Create a successful compose + composeID, err = api.store.PushTestCompose(imageType, bp, api.allRepositories(), packages, buildPackages, cr.Size, targets, true) + } else { + composeID, err = api.store.PushCompose(imageType, bp, api.allRepositories(), packages, buildPackages, cr.Size, targets) + } // TODO: we should probably do some kind of blueprint validation in future // for now, let's just 500 and bail out