diff --git a/api/mirror.go b/api/mirror.go index aa4af0a2..bf8d3bad 100644 --- a/api/mirror.go +++ b/api/mirror.go @@ -66,17 +66,26 @@ func uniqueStrings(input []string) []string { // @Description Each mirror is returned as in “show” API. // @Tags Mirrors // @Produce json -// @Success 200 {array} deb.RemoteRepo +// @Success 200 {array} remoteRepoResponse // @Router /api/mirrors [get] func apiMirrorsList(c *gin.Context) { collectionFactory := context.NewCollectionFactory() collection := collectionFactory.RemoteRepoCollection() - result := []*deb.RemoteRepo{} - _ = collection.ForEach(func(repo *deb.RemoteRepo) error { - result = append(result, repo) + result := []remoteRepoResponse{} + err := collection.ForEach(func(repo *deb.RemoteRepo) error { + err := collection.LoadComplete(repo) + if err != nil { + return err + } + + result = append(result, newRemoteRepoResponse(repo)) return nil }) + if err != nil { + AbortWithJSONError(c, 500, fmt.Errorf("unable to show: %s", err)) + return + } c.JSON(200, result) } @@ -264,6 +273,7 @@ func apiMirrorsShow(c *gin.Context) { err = collection.LoadComplete(repo) if err != nil { AbortWithJSONError(c, 500, fmt.Errorf("unable to show: %s", err)) + return } c.JSON(200, repo) diff --git a/api/mirror_test.go b/api/mirror_test.go index cb64d485..65433e7f 100644 --- a/api/mirror_test.go +++ b/api/mirror_test.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" + "github.com/aptly-dev/aptly/deb" "github.com/gin-gonic/gin" . "gopkg.in/check.v1" ) @@ -17,7 +18,10 @@ var _ = Suite(&MirrorSuite{}) func (s *MirrorSuite) TestGetMirrors(c *C) { response, _ := s.HTTPRequest("GET", "/api/mirrors", nil) c.Check(response.Code, Equals, 200) - c.Check(response.Body.String(), Equals, "[]") + + var mirrors []map[string]interface{} + err := json.Unmarshal(response.Body.Bytes(), &mirrors) + c.Assert(err, IsNil) } func (s *MirrorSuite) TestDeleteMirrorNonExisting(c *C) { @@ -53,3 +57,49 @@ func (s *MirrorSuite) TestCreateMirror(c *C) { c.Check(response.Code, Equals, 400) c.Check(response.Body.String(), Equals, "") } + +func (s *MirrorSuite) TestGetMirrorsIncludesNumPackages(c *C) { + collection := s.context.NewCollectionFactory().RemoteRepoCollection() + + repo, err := deb.NewRemoteRepo("count-mirror", "http://example.com/debian", "stable", []string{"main"}, []string{}, false, false, false, false) + c.Assert(err, IsNil) + + err = collection.Add(repo) + c.Assert(err, IsNil) + putRawDBValue(c, &s.APISuite, repo.RefKey(), makePackageRefList(c).Encode()) + + response, err := s.HTTPRequest("GET", "/api/mirrors", nil) + c.Assert(err, IsNil) + c.Assert(response.Code, Equals, 200) + + var mirrors []map[string]interface{} + err = json.Unmarshal(response.Body.Bytes(), &mirrors) + c.Assert(err, IsNil) + + found := false + for _, mirror := range mirrors { + if mirror["Name"] == "count-mirror" { + found = true + value, ok := mirror["NumPackages"] + c.Assert(ok, Equals, true) + c.Assert(value, Equals, float64(2)) + break + } + } + + c.Assert(found, Equals, true) +} + +func (s *MirrorSuite) TestGetMirrorsReturns500OnCorruptRefList(c *C) { + collection := s.context.NewCollectionFactory().RemoteRepoCollection() + + repo, err := deb.NewRemoteRepo("broken-mirror", "http://example.com/debian", "stable", []string{"main"}, []string{}, false, false, false, false) + c.Assert(err, IsNil) + c.Assert(collection.Add(repo), IsNil) + putRawDBValue(c, &s.APISuite, repo.RefKey(), []byte("not-msgpack")) + + response, err := s.HTTPRequest("GET", "/api/mirrors", nil) + c.Assert(err, IsNil) + c.Assert(response.Code, Equals, 500) + c.Assert(response.Body.String(), Matches, ".*unable to show:.*") +} diff --git a/api/package_count_response.go b/api/package_count_response.go new file mode 100644 index 00000000..4edb215d --- /dev/null +++ b/api/package_count_response.go @@ -0,0 +1,30 @@ +package api + +import "github.com/aptly-dev/aptly/deb" + +type remoteRepoResponse struct { + *deb.RemoteRepo + NumPackages int `json:"NumPackages"` +} + +type localRepoResponse struct { + *deb.LocalRepo + NumPackages int `json:"NumPackages"` +} + +type snapshotResponse struct { + *deb.Snapshot + NumPackages int `json:"NumPackages"` +} + +func newRemoteRepoResponse(repo *deb.RemoteRepo) remoteRepoResponse { + return remoteRepoResponse{RemoteRepo: repo, NumPackages: repo.NumPackages()} +} + +func newLocalRepoResponse(repo *deb.LocalRepo) localRepoResponse { + return localRepoResponse{LocalRepo: repo, NumPackages: repo.NumPackages()} +} + +func newSnapshotResponse(snapshot *deb.Snapshot) snapshotResponse { + return snapshotResponse{Snapshot: snapshot, NumPackages: snapshot.NumPackages()} +} diff --git a/api/package_count_test_helpers_test.go b/api/package_count_test_helpers_test.go new file mode 100644 index 00000000..fc86ef3c --- /dev/null +++ b/api/package_count_test_helpers_test.go @@ -0,0 +1,19 @@ +package api + +import ( + "github.com/aptly-dev/aptly/deb" + . "gopkg.in/check.v1" +) + +func makePackageRefList(c *C) *deb.PackageRefList { + list := deb.NewPackageList() + c.Assert(list.Add(&deb.Package{Name: "libcount", Version: "1.0", Architecture: "amd64"}), IsNil) + c.Assert(list.Add(&deb.Package{Name: "appcount", Version: "2.0", Architecture: "all"}), IsNil) + return deb.NewPackageRefListFromPackageList(list) +} + +func putRawDBValue(c *C, s *APISuite, key []byte, value []byte) { + db, err := s.context.Database() + c.Assert(err, IsNil) + c.Assert(db.Put(key, value), IsNil) +} \ No newline at end of file diff --git a/api/repos.go b/api/repos.go index 6f418bf8..77dd5172 100644 --- a/api/repos.go +++ b/api/repos.go @@ -69,17 +69,26 @@ func reposServeInAPIMode(c *gin.Context) { // @Description Each repo is returned as in “show” API. // @Tags Repos // @Produce json -// @Success 200 {array} deb.LocalRepo +// @Success 200 {array} localRepoResponse // @Router /api/repos [get] func apiReposList(c *gin.Context) { - result := []*deb.LocalRepo{} + result := []localRepoResponse{} collectionFactory := context.NewCollectionFactory() collection := collectionFactory.LocalRepoCollection() - _ = collection.ForEach(func(r *deb.LocalRepo) error { - result = append(result, r) + err := collection.ForEach(func(r *deb.LocalRepo) error { + err := collection.LoadComplete(r) + if err != nil { + return err + } + + result = append(result, newLocalRepoResponse(r)) return nil }) + if err != nil { + AbortWithJSONError(c, 500, err) + return + } c.JSON(200, result) } diff --git a/api/repos_test.go b/api/repos_test.go new file mode 100644 index 00000000..55117316 --- /dev/null +++ b/api/repos_test.go @@ -0,0 +1,63 @@ +package api + +import ( + "bytes" + "encoding/json" + + "github.com/aptly-dev/aptly/deb" + "github.com/gin-gonic/gin" + . "gopkg.in/check.v1" +) + +type ReposSuite struct { + APISuite +} + +var _ = Suite(&ReposSuite{}) + +func (s *ReposSuite) TestGetReposIncludesNumPackages(c *C) { + collection := s.context.NewCollectionFactory().LocalRepoCollection() + repo := deb.NewLocalRepo("count-repo-list", "") + repo.UpdateRefList(makePackageRefList(c)) + c.Assert(collection.Add(repo), IsNil) + + response, err := s.HTTPRequest("GET", "/api/repos", nil) + c.Assert(err, IsNil) + c.Assert(response.Code, Equals, 200) + + var repos []map[string]interface{} + err = json.Unmarshal(response.Body.Bytes(), &repos) + c.Assert(err, IsNil) + + found := false + for _, repo := range repos { + if repo["Name"] == "count-repo-list" { + found = true + value, ok := repo["NumPackages"] + c.Assert(ok, Equals, true) + c.Assert(value, Equals, float64(2)) + break + } + } + + c.Assert(found, Equals, true) +} + +func (s *ReposSuite) TestGetReposReturns500OnCorruptRefList(c *C) { + body, err := json.Marshal(gin.H{"Name": "broken-repo-list"}) + c.Assert(err, IsNil) + + response, err := s.HTTPRequest("POST", "/api/repos", bytes.NewReader(body)) + c.Assert(err, IsNil) + c.Assert(response.Code, Equals, 201) + + collection := s.context.NewCollectionFactory().LocalRepoCollection() + repo, err := collection.ByName("broken-repo-list") + c.Assert(err, IsNil) + putRawDBValue(c, &s.APISuite, repo.RefKey(), []byte("not-msgpack")) + + response, err = s.HTTPRequest("GET", "/api/repos", nil) + c.Assert(err, IsNil) + c.Assert(response.Code, Equals, 500) + c.Assert(response.Body.String(), Matches, ".*msgpack.*|.*decode.*") +} diff --git a/api/snapshot.go b/api/snapshot.go index 24f276c5..2c50566f 100644 --- a/api/snapshot.go +++ b/api/snapshot.go @@ -20,7 +20,7 @@ import ( // @Description Each snapshot is returned as in “show” API. // @Tags Snapshots // @Produce json -// @Success 200 {array} deb.Snapshot +// @Success 200 {array} snapshotResponse // @Router /api/snapshots [get] func apiSnapshotsList(c *gin.Context) { SortMethodString := c.Request.URL.Query().Get("sort") @@ -32,11 +32,20 @@ func apiSnapshotsList(c *gin.Context) { SortMethodString = "name" } - result := []*deb.Snapshot{} - _ = collection.ForEachSorted(SortMethodString, func(snapshot *deb.Snapshot) error { - result = append(result, snapshot) + result := []snapshotResponse{} + err := collection.ForEachSorted(SortMethodString, func(snapshot *deb.Snapshot) error { + err := collection.LoadComplete(snapshot) + if err != nil { + return err + } + + result = append(result, newSnapshotResponse(snapshot)) return nil }) + if err != nil { + AbortWithJSONError(c, 500, err) + return + } c.JSON(200, result) } diff --git a/api/snapshot_test.go b/api/snapshot_test.go new file mode 100644 index 00000000..36c50809 --- /dev/null +++ b/api/snapshot_test.go @@ -0,0 +1,53 @@ +package api + +import ( + "encoding/json" + + "github.com/aptly-dev/aptly/deb" + . "gopkg.in/check.v1" +) + +type SnapshotsSuite struct { + APISuite +} + +var _ = Suite(&SnapshotsSuite{}) + +func (s *SnapshotsSuite) TestGetSnapshotsIncludesNumPackages(c *C) { + collection := s.context.NewCollectionFactory().SnapshotCollection() + snapshot := deb.NewSnapshotFromRefList("count-snapshot-list", nil, makePackageRefList(c), "") + c.Assert(collection.Add(snapshot), IsNil) + + response, err := s.HTTPRequest("GET", "/api/snapshots", nil) + c.Assert(err, IsNil) + c.Assert(response.Code, Equals, 200) + + var snapshots []map[string]interface{} + err = json.Unmarshal(response.Body.Bytes(), &snapshots) + c.Assert(err, IsNil) + + found := false + for _, snapshot := range snapshots { + if snapshot["Name"] == "count-snapshot-list" { + found = true + value, ok := snapshot["NumPackages"] + c.Assert(ok, Equals, true) + c.Assert(value, Equals, float64(2)) + break + } + } + + c.Assert(found, Equals, true) +} + +func (s *SnapshotsSuite) TestGetSnapshotsReturns500OnCorruptRefList(c *C) { + collection := s.context.NewCollectionFactory().SnapshotCollection() + snapshot := deb.NewSnapshotFromRefList("broken-snapshot-list", nil, makePackageRefList(c), "") + c.Assert(collection.Add(snapshot), IsNil) + putRawDBValue(c, &s.APISuite, snapshot.RefKey(), []byte("not-msgpack")) + + response, err := s.HTTPRequest("GET", "/api/snapshots", nil) + c.Assert(err, IsNil) + c.Assert(response.Code, Equals, 500) + c.Assert(response.Body.String(), Matches, ".*msgpack.*|.*decode.*") +}