mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-01-11 03:11:50 +00:00
Add first /repos/ API, command api serve. #116
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,6 +1,6 @@
|
|||||||
GOVERSION=$(shell go version | awk '{print $$3;}')
|
GOVERSION=$(shell go version | awk '{print $$3;}')
|
||||||
PACKAGES=context database deb files http query s3 utils
|
PACKAGES=context database deb files http query s3 utils
|
||||||
ALL_PACKAGES=aptly context cmd console database deb files http query s3 utils
|
ALL_PACKAGES=api aptly context cmd console database deb files http query s3 utils
|
||||||
BINPATH=$(abspath ./_vendor/bin)
|
BINPATH=$(abspath ./_vendor/bin)
|
||||||
GOM_ENVIRONMENT=-test
|
GOM_ENVIRONMENT=-test
|
||||||
PYTHON?=python
|
PYTHON?=python
|
||||||
|
|||||||
2
api/api.go
Normal file
2
api/api.go
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
// Package api provides implementation of aptly REST API
|
||||||
|
package api
|
||||||
184
api/repos.go
Normal file
184
api/repos.go
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/smira/aptly/deb"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GET /api/repos
|
||||||
|
func apiReposList(c *gin.Context) {
|
||||||
|
result := []*deb.LocalRepo{}
|
||||||
|
|
||||||
|
collection := context.CollectionFactory().LocalRepoCollection()
|
||||||
|
collection.RLock()
|
||||||
|
defer collection.RUnlock()
|
||||||
|
|
||||||
|
context.CollectionFactory().LocalRepoCollection().ForEach(func(r *deb.LocalRepo) error {
|
||||||
|
result = append(result, r)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
c.JSON(200, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /api/repos
|
||||||
|
func apiReposCreate(c *gin.Context) {
|
||||||
|
var b struct {
|
||||||
|
Name string `binding:"required"`
|
||||||
|
Comment string
|
||||||
|
DefaultDistribution string
|
||||||
|
DefaultComponent string
|
||||||
|
}
|
||||||
|
|
||||||
|
if !c.Bind(&b) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
repo := deb.NewLocalRepo(b.Name, b.Comment)
|
||||||
|
repo.DefaultComponent = b.DefaultComponent
|
||||||
|
repo.DefaultDistribution = b.DefaultDistribution
|
||||||
|
|
||||||
|
collection := context.CollectionFactory().LocalRepoCollection()
|
||||||
|
collection.Lock()
|
||||||
|
defer collection.Unlock()
|
||||||
|
|
||||||
|
err := context.CollectionFactory().LocalRepoCollection().Add(repo)
|
||||||
|
if err != nil {
|
||||||
|
c.Fail(400, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(201, repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /api/repos/:name
|
||||||
|
func apiReposEdit(c *gin.Context) {
|
||||||
|
var b struct {
|
||||||
|
Comment string
|
||||||
|
DefaultDistribution string
|
||||||
|
DefaultComponent string
|
||||||
|
}
|
||||||
|
|
||||||
|
if !c.Bind(&b) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
collection := context.CollectionFactory().LocalRepoCollection()
|
||||||
|
collection.Lock()
|
||||||
|
defer collection.Unlock()
|
||||||
|
|
||||||
|
repo, err := collection.ByName(c.Params.ByName("name"))
|
||||||
|
if err != nil {
|
||||||
|
c.Fail(404, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.Comment != "" {
|
||||||
|
repo.Comment = b.Comment
|
||||||
|
}
|
||||||
|
if b.DefaultDistribution != "" {
|
||||||
|
repo.DefaultDistribution = b.DefaultDistribution
|
||||||
|
}
|
||||||
|
if b.DefaultComponent != "" {
|
||||||
|
repo.DefaultComponent = b.DefaultComponent
|
||||||
|
}
|
||||||
|
|
||||||
|
err = collection.Update(repo)
|
||||||
|
if err != nil {
|
||||||
|
c.Fail(500, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(200, repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /api/repos/:name
|
||||||
|
func apiReposShow(c *gin.Context) {
|
||||||
|
collection := context.CollectionFactory().LocalRepoCollection()
|
||||||
|
collection.RLock()
|
||||||
|
defer collection.RUnlock()
|
||||||
|
|
||||||
|
repo, err := collection.ByName(c.Params.ByName("name"))
|
||||||
|
if err != nil {
|
||||||
|
c.Fail(404, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(200, repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /api/repos/:name
|
||||||
|
func apiReposDrop(c *gin.Context) {
|
||||||
|
var b struct {
|
||||||
|
Force bool
|
||||||
|
}
|
||||||
|
|
||||||
|
if !c.Bind(&b) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
collection := context.CollectionFactory().LocalRepoCollection()
|
||||||
|
collection.Lock()
|
||||||
|
defer collection.Unlock()
|
||||||
|
|
||||||
|
snapshotCollection := context.CollectionFactory().SnapshotCollection()
|
||||||
|
snapshotCollection.RLock()
|
||||||
|
defer snapshotCollection.RUnlock()
|
||||||
|
|
||||||
|
publishedCollection := context.CollectionFactory().PublishedRepoCollection()
|
||||||
|
publishedCollection.RLock()
|
||||||
|
defer publishedCollection.RUnlock()
|
||||||
|
|
||||||
|
repo, err := collection.ByName(c.Params.ByName("name"))
|
||||||
|
if err != nil {
|
||||||
|
c.Fail(404, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
published := publishedCollection.ByLocalRepo(repo)
|
||||||
|
if len(published) > 0 {
|
||||||
|
c.Fail(409, fmt.Errorf("unable to drop, local repo is published"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshots := snapshotCollection.ByLocalRepoSource(repo)
|
||||||
|
if len(snapshots) > 0 {
|
||||||
|
c.Fail(409, fmt.Errorf("unable to drop, local repo has snapshots, use Force to override"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = collection.Drop(repo)
|
||||||
|
if err != nil {
|
||||||
|
c.Fail(500, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(200, gin.H{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /api/repos/:name/packages
|
||||||
|
func apiReposPackagesShow(c *gin.Context) {
|
||||||
|
collection := context.CollectionFactory().LocalRepoCollection()
|
||||||
|
collection.RLock()
|
||||||
|
defer collection.RUnlock()
|
||||||
|
|
||||||
|
repo, err := collection.ByName(c.Params.ByName("name"))
|
||||||
|
if err != nil {
|
||||||
|
c.Fail(404, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = collection.LoadComplete(repo)
|
||||||
|
if err != nil {
|
||||||
|
c.Fail(500, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(200, repo.RefList().Strings())
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /repos/:name/packages
|
||||||
|
func apiReposPackagesAdd(c *gin.Context) {
|
||||||
|
|
||||||
|
}
|
||||||
31
api/router.go
Normal file
31
api/router.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
ctx "github.com/smira/aptly/context"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
var context *ctx.AptlyContext
|
||||||
|
|
||||||
|
// Router returns prebuilt with routes http.Handler
|
||||||
|
func Router(c *ctx.AptlyContext) http.Handler {
|
||||||
|
context = c
|
||||||
|
|
||||||
|
router := gin.Default()
|
||||||
|
router.Use(gin.ErrorLogger())
|
||||||
|
|
||||||
|
root := router.Group("/api")
|
||||||
|
{
|
||||||
|
root.GET("/repos", apiReposList)
|
||||||
|
root.POST("/repos", apiReposCreate)
|
||||||
|
root.GET("/repos/:name", apiReposShow)
|
||||||
|
root.PUT("/repos/:name", apiReposEdit)
|
||||||
|
root.DELETE("/repos/:name", apiReposDrop)
|
||||||
|
|
||||||
|
root.GET("/repos/:name/packages", apiReposPackagesShow)
|
||||||
|
root.POST("/repos/:name/packages", apiReposPackagesAdd)
|
||||||
|
}
|
||||||
|
|
||||||
|
return router
|
||||||
|
}
|
||||||
15
cmd/api.go
Normal file
15
cmd/api.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/smira/commander"
|
||||||
|
)
|
||||||
|
|
||||||
|
func makeCmdAPI() *commander.Command {
|
||||||
|
return &commander.Command{
|
||||||
|
UsageLine: "api",
|
||||||
|
Short: "start API server/issue requests",
|
||||||
|
Subcommands: []*commander.Command{
|
||||||
|
makeCmdAPIServe(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
52
cmd/api_serve.go
Normal file
52
cmd/api_serve.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/smira/aptly/api"
|
||||||
|
"github.com/smira/commander"
|
||||||
|
"github.com/smira/flag"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func aptlyAPIServe(cmd *commander.Command, args []string) error {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(args) != 0 {
|
||||||
|
cmd.Usage()
|
||||||
|
return commander.ErrCommandError
|
||||||
|
}
|
||||||
|
|
||||||
|
listen := context.Flags().Lookup("listen").Value.String()
|
||||||
|
|
||||||
|
fmt.Printf("\nStarting web server at: %s (press Ctrl+C to quit)...\n", listen)
|
||||||
|
|
||||||
|
err = http.ListenAndServe(listen, api.Router(context))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to serve: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeCmdAPIServe() *commander.Command {
|
||||||
|
cmd := &commander.Command{
|
||||||
|
Run: aptlyAPIServe,
|
||||||
|
UsageLine: "serve",
|
||||||
|
Short: "start API HTTP service",
|
||||||
|
Long: `
|
||||||
|
Stat HTTP server with aptly REST API.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
$ aptly api serve -listen=:8080
|
||||||
|
`,
|
||||||
|
Flag: *flag.NewFlagSet("aptly-serve", flag.ExitOnError),
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Flag.String("listen", ":8080", "host:port for HTTP listening")
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
|
||||||
|
}
|
||||||
@@ -76,7 +76,7 @@ package environment to new version.`,
|
|||||||
makeCmdPublish(),
|
makeCmdPublish(),
|
||||||
makeCmdVersion(),
|
makeCmdVersion(),
|
||||||
makeCmdPackage(),
|
makeCmdPackage(),
|
||||||
//makeCmdAPI(),
|
makeCmdAPI(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ aptly - Debian repository management tool
|
|||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
|
|
||||||
|
api start API server/issue requests
|
||||||
db manage aptly's internal database and package pool
|
db manage aptly's internal database and package pool
|
||||||
graph render graph of relationships
|
graph render graph of relationships
|
||||||
mirror manage mirrors of remote repositories
|
mirror manage mirrors of remote repositories
|
||||||
|
|||||||
Reference in New Issue
Block a user