Add blueprint workspace diff
The list of changes between the committed blueprint and its workspace are returned when a user requests the diff. Each change includes the new(added) or the old(removed) package.
This commit is contained in:
parent
e14c48ff61
commit
e24bfcf7d0
3 changed files with 88 additions and 5 deletions
|
|
@ -462,13 +462,72 @@ func (api *API) blueprintsDepsolveHandler(writer http.ResponseWriter, request *h
|
|||
})
|
||||
}
|
||||
|
||||
func (api *API) blueprintsDiffHandler(writer http.ResponseWriter, request *http.Request, _ httprouter.Params) {
|
||||
var reply struct {
|
||||
Diff []interface{} `json:"diff"`
|
||||
func (api *API) blueprintsDiffHandler(writer http.ResponseWriter, request *http.Request, params httprouter.Params) {
|
||||
type pack struct {
|
||||
Package blueprintPackage `json:"Package"`
|
||||
}
|
||||
|
||||
reply.Diff = make([]interface{}, 0)
|
||||
json.NewEncoder(writer).Encode(reply)
|
||||
type diff struct {
|
||||
New *pack `json:"new"`
|
||||
Old *pack `json:"old"`
|
||||
}
|
||||
|
||||
type reply struct {
|
||||
Diffs []diff `json:"diff"`
|
||||
}
|
||||
|
||||
name := params.ByName("blueprint")
|
||||
if len(name) == 0 {
|
||||
statusResponseError(writer, http.StatusNotFound, "no blueprint name given")
|
||||
return
|
||||
}
|
||||
fromCommit := params.ByName("from")
|
||||
if len(fromCommit) == 0 || fromCommit != "NEWEST" {
|
||||
statusResponseError(writer, http.StatusNotFound, "invalid from commit ID given")
|
||||
return
|
||||
}
|
||||
toCommit := params.ByName("to")
|
||||
if len(toCommit) == 0 || toCommit != "WORKSPACE" {
|
||||
statusResponseError(writer, http.StatusNotFound, "invalid to commit ID given")
|
||||
return
|
||||
}
|
||||
|
||||
// Fetch old and new blueprint details from store and return error if not found
|
||||
var oldBlueprint, newBlueprint 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)
|
||||
diffs := []diff{}
|
||||
|
||||
for _, oldPackage := range oldBlueprint.Packages {
|
||||
oldMap[oldPackage.Name] = oldPackage
|
||||
}
|
||||
|
||||
// For each package in new blueprint check if the old one contains it
|
||||
for _, newPackage := range newSlice {
|
||||
oldPackage, found := oldMap[newPackage.Name]
|
||||
// If found remove from old packages map but otherwise create a diff with the added package
|
||||
if found {
|
||||
delete(oldMap, oldPackage.Name)
|
||||
// Create a diff if the versions changed
|
||||
if oldPackage.Version != newPackage.Version {
|
||||
diffs = append(diffs, diff{Old: &pack{oldPackage}, New: &pack{newPackage}})
|
||||
}
|
||||
} else {
|
||||
diffs = append(diffs, diff{Old: nil, New: &pack{newPackage}})
|
||||
}
|
||||
}
|
||||
|
||||
// All packages remaining in the old packages map have been removed in the new blueprint so create a diff
|
||||
for _, oldPackage := range oldMap {
|
||||
diffs = append(diffs, diff{Old: &pack{oldPackage}, New: nil})
|
||||
}
|
||||
|
||||
json.NewEncoder(writer).Encode(reply{diffs})
|
||||
}
|
||||
|
||||
func (api *API) blueprintsNewHandler(writer http.ResponseWriter, request *http.Request, _ httprouter.Params) {
|
||||
|
|
|
|||
|
|
@ -135,6 +135,9 @@ func TestBlueprints(t *testing.T) {
|
|||
testRoute(t, api, "GET", "/api/v0/blueprints/info/test", ``,
|
||||
http.StatusOK, `{"blueprints":[{"name":"test","description":"Test","modules":[],"packages":[{"name":"systemd","version":"123"}],"version":"0"}],
|
||||
"changes":[{"name":"test","changed":true}], "errors":[]}`)
|
||||
|
||||
testRoute(t, api, "GET", "/api/v0/blueprints/diff/test/NEWEST/WORKSPACE", ``,
|
||||
http.StatusOK, `{"diff":[{"new":{"Package":{"name":"systemd","version":"123"}},"old":null},{"new":null,"old":{"Package":{"name":"httpd","version":"2.4.*"}}}]}`)
|
||||
}
|
||||
|
||||
func TestCompose(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -109,6 +109,27 @@ func (s *store) getBlueprint(name string, bp *blueprint, changed *bool) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (s *store) getBlueprintCommitted(name string, bp *blueprint) bool {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
|
||||
var ok bool
|
||||
*bp, ok = s.Blueprints[name]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
// cockpit-composer cannot deal with missing "packages" or "modules"
|
||||
if bp.Packages == nil {
|
||||
bp.Packages = []blueprintPackage{}
|
||||
}
|
||||
if bp.Modules == nil {
|
||||
bp.Modules = []blueprintPackage{}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *store) pushBlueprint(bp blueprint) {
|
||||
s.change(func() {
|
||||
delete(s.Workspace, bp.Name)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue