weldr: split blueprint into its own package

This will contain all the translation logic from blueprints to pipelines,
which will constitute the main part of composer, so let's separate that
out from the API.

Signed-off-by: Tom Gundersen <teg@jklm.no>
This commit is contained in:
Tom Gundersen 2019-10-03 19:38:23 +02:00 committed by Lars Karlitski
parent 329964f2ab
commit 949d3464b5
3 changed files with 70 additions and 61 deletions

View file

@ -11,6 +11,7 @@ import (
"github.com/google/uuid"
"github.com/julienschmidt/httprouter"
"osbuild-composer/internal/blueprint"
"osbuild-composer/internal/job"
"osbuild-composer/internal/rpmmd"
)
@ -37,12 +38,12 @@ func New(repo rpmmd.RepoConfig, packages rpmmd.PackageList, logger *log.Logger,
// sample blueprint on first run
if initialState == nil {
api.store.pushBlueprint(blueprint{
api.store.pushBlueprint(blueprint.Blueprint{
Name: "example",
Description: "An Example",
Version: "1",
Packages: []blueprintPackage{{"httpd", "2.*"}},
Modules: []blueprintPackage{},
Packages: []blueprint.Package{{"httpd", "2.*"}},
Modules: []blueprint.Package{},
})
}
@ -399,9 +400,9 @@ func (api *API) blueprintsInfoHandler(writer http.ResponseWriter, request *http.
Name string `json:"name"`
}
type reply struct {
Blueprints []blueprint `json:"blueprints"`
Changes []change `json:"changes"`
Errors []string `json:"errors"`
Blueprints []blueprint.Blueprint `json:"blueprints"`
Changes []change `json:"changes"`
Errors []string `json:"errors"`
}
names := strings.Split(params.ByName("blueprints"), ",")
@ -410,10 +411,10 @@ func (api *API) blueprintsInfoHandler(writer http.ResponseWriter, request *http.
return
}
blueprints := []blueprint{}
blueprints := []blueprint.Blueprint{}
changes := []change{}
for _, name := range names {
var blueprint blueprint
var blueprint blueprint.Blueprint
var changed bool
if !api.store.getBlueprint(name, &blueprint, &changed) {
statusResponseError(writer, http.StatusNotFound)
@ -432,7 +433,7 @@ func (api *API) blueprintsInfoHandler(writer http.ResponseWriter, request *http.
func (api *API) blueprintsDepsolveHandler(writer http.ResponseWriter, request *http.Request, params httprouter.Params) {
type entry struct {
Blueprint blueprint `json:"blueprint"`
Blueprint blueprint.Blueprint `json:"blueprint"`
Dependencies []rpmmd.PackageSpec `json:"dependencies"`
}
type reply struct {
@ -448,7 +449,7 @@ func (api *API) blueprintsDepsolveHandler(writer http.ResponseWriter, request *h
blueprints := []entry{}
for _, name := range names {
var blueprint blueprint
var blueprint blueprint.Blueprint
if !api.store.getBlueprint(name, &blueprint, nil) {
statusResponseError(writer, http.StatusNotFound)
return
@ -478,7 +479,7 @@ func (api *API) blueprintsDepsolveHandler(writer http.ResponseWriter, request *h
func (api *API) blueprintsDiffHandler(writer http.ResponseWriter, request *http.Request, params httprouter.Params) {
type pack struct {
Package blueprintPackage `json:"Package"`
Package blueprint.Package `json:"Package"`
}
type diff struct {
@ -507,14 +508,14 @@ func (api *API) blueprintsDiffHandler(writer http.ResponseWriter, request *http.
}
// Fetch old and new blueprint details from store and return error if not found
var oldBlueprint, newBlueprint blueprint
var oldBlueprint, newBlueprint blueprint.Blueprint
if !api.store.getBlueprintCommitted(name, &oldBlueprint) || !api.store.getBlueprint(name, &newBlueprint, nil) {
statusResponseError(writer, http.StatusNotFound)
return
}
newSlice := newBlueprint.Packages
oldMap := make(map[string]blueprintPackage)
oldMap := make(map[string]blueprint.Package)
diffs := []diff{}
for _, oldPackage := range oldBlueprint.Packages {
@ -551,7 +552,7 @@ func (api *API) blueprintsNewHandler(writer http.ResponseWriter, request *http.R
return
}
var blueprint blueprint
var blueprint blueprint.Blueprint
err := json.NewDecoder(request.Body).Decode(&blueprint)
if err != nil {
statusResponseError(writer, http.StatusBadRequest, "invalid blueprint: "+err.Error())
@ -570,7 +571,7 @@ func (api *API) blueprintsWorkspaceHandler(writer http.ResponseWriter, request *
return
}
var blueprint blueprint
var blueprint blueprint.Blueprint
err := json.NewDecoder(request.Body).Decode(&blueprint)
if err != nil {
statusResponseError(writer, http.StatusBadRequest, "invalid blueprint: "+err.Error())
@ -624,7 +625,7 @@ func (api *API) composeHandler(writer http.ResponseWriter, httpRequest *http.Req
Status: true,
}
bp := blueprint{}
bp := blueprint.Blueprint{}
changed := false
found := api.store.getBlueprint(cr.BlueprintName, &bp, &changed) // TODO: what to do with changed?

View file

@ -3,8 +3,8 @@ package weldr
import (
"encoding/json"
"log"
"osbuild-composer/internal/blueprint"
"osbuild-composer/internal/job"
"osbuild-composer/internal/pipeline"
"osbuild-composer/internal/target"
"sort"
"sync"
@ -14,9 +14,9 @@ import (
)
type store struct {
Blueprints map[string]blueprint `json:"blueprints"`
Workspace map[string]blueprint `json:"workspace"`
Composes map[uuid.UUID]compose `json:"composes"`
Blueprints map[string]blueprint.Blueprint `json:"blueprints"`
Workspace map[string]blueprint.Blueprint `json:"workspace"`
Composes map[uuid.UUID]compose `json:"composes"`
mu sync.RWMutex // protects all fields
pendingJobs chan<- job.Job
@ -24,28 +24,14 @@ type store struct {
stateChannel chan<- []byte
}
type blueprint struct {
Name string `json:"name"`
Description string `json:"description"`
Version string `json:"version,omitempty"`
Packages []blueprintPackage `json:"packages"`
Modules []blueprintPackage `json:"modules"`
Groups []blueprintPackage `json:"groups"`
}
type blueprintPackage struct {
Name string `json:"name"`
Version string `json:"version,omitempty"`
}
type compose struct {
QueueStatus string `json:"queue_status"`
Blueprint *blueprint `json:"blueprint"`
OutputType string `json:"output-type"`
Targets []*target.Target `json:"targets"`
JobCreated time.Time `json:"job_created"`
JobStarted time.Time `json:"job_started"`
JobFinished time.Time `json:"job_finished"`
QueueStatus string `json:"queue_status"`
Blueprint *blueprint.Blueprint `json:"blueprint"`
OutputType string `json:"output-type"`
Targets []*target.Target `json:"targets"`
JobCreated time.Time `json:"job_created"`
JobStarted time.Time `json:"job_started"`
JobFinished time.Time `json:"job_finished"`
}
func newStore(initialState []byte, stateChannel chan<- []byte, pendingJobs chan<- job.Job, jobUpdates <-chan job.Status) *store {
@ -59,10 +45,10 @@ func newStore(initialState []byte, stateChannel chan<- []byte, pendingJobs chan<
}
if s.Blueprints == nil {
s.Blueprints = make(map[string]blueprint)
s.Blueprints = make(map[string]blueprint.Blueprint)
}
if s.Workspace == nil {
s.Workspace = make(map[string]blueprint)
s.Workspace = make(map[string]blueprint.Blueprint)
}
if s.Composes == nil {
// TODO: push waiting/running composes to workers again
@ -128,7 +114,7 @@ func (s *store) listBlueprints() []string {
return names
}
func (s *store) getBlueprint(name string, bp *blueprint, changed *bool) bool {
func (s *store) getBlueprint(name string, bp *blueprint.Blueprint, changed *bool) bool {
s.mu.RLock()
defer s.mu.RUnlock()
@ -144,13 +130,13 @@ func (s *store) getBlueprint(name string, bp *blueprint, changed *bool) bool {
// cockpit-composer cannot deal with missing "packages" or "modules"
if bp.Packages == nil {
bp.Packages = []blueprintPackage{}
bp.Packages = []blueprint.Package{}
}
if bp.Modules == nil {
bp.Modules = []blueprintPackage{}
bp.Modules = []blueprint.Package{}
}
if bp.Groups == nil {
bp.Groups = []blueprintPackage{}
bp.Groups = []blueprint.Package{}
}
if bp.Version == "" {
bp.Version = "0.0.0"
@ -163,7 +149,7 @@ func (s *store) getBlueprint(name string, bp *blueprint, changed *bool) bool {
return true
}
func (s *store) getBlueprintCommitted(name string, bp *blueprint) bool {
func (s *store) getBlueprintCommitted(name string, bp *blueprint.Blueprint) bool {
s.mu.RLock()
defer s.mu.RUnlock()
@ -175,13 +161,13 @@ func (s *store) getBlueprintCommitted(name string, bp *blueprint) bool {
// cockpit-composer cannot deal with missing "packages" or "modules"
if bp.Packages == nil {
bp.Packages = []blueprintPackage{}
bp.Packages = []blueprint.Package{}
}
if bp.Modules == nil {
bp.Modules = []blueprintPackage{}
bp.Modules = []blueprint.Package{}
}
if bp.Groups == nil {
bp.Groups = []blueprintPackage{}
bp.Groups = []blueprint.Package{}
}
if bp.Version == "" {
bp.Version = "0.0.0"
@ -190,14 +176,14 @@ func (s *store) getBlueprintCommitted(name string, bp *blueprint) bool {
return true
}
func (s *store) pushBlueprint(bp blueprint) {
func (s *store) pushBlueprint(bp blueprint.Blueprint) {
s.change(func() {
delete(s.Workspace, bp.Name)
s.Blueprints[bp.Name] = bp
})
}
func (s *store) pushBlueprintToWorkspace(bp blueprint) {
func (s *store) pushBlueprintToWorkspace(bp blueprint.Blueprint) {
s.change(func() {
s.Workspace[bp.Name] = bp
})
@ -216,7 +202,7 @@ func (s *store) deleteBlueprintFromWorkspace(name string) {
})
}
func (s *store) addCompose(composeID uuid.UUID, bp *blueprint, composeType string) {
func (s *store) addCompose(composeID uuid.UUID, bp *blueprint.Blueprint, composeType string) {
targets := []*target.Target{
target.NewLocalTarget(target.NewLocalTargetOptions("/var/lib/osbuild-composer/outputs/" + composeID.String())),
}
@ -231,13 +217,7 @@ func (s *store) addCompose(composeID uuid.UUID, bp *blueprint, composeType strin
})
s.pendingJobs <- job.Job{
ComposeID: composeID,
Pipeline: bp.translateToPipeline(composeType),
Pipeline: bp.TranslateToPipeline(composeType),
Targets: targets,
}
}
func (b *blueprint) translateToPipeline(outputFormat string) *pipeline.Pipeline {
p := &pipeline.Pipeline{}
p.SetAssembler(pipeline.NewTarAssembler(pipeline.NewTarAssemblerOptions("image.tar")))
return p
}