Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/swagger #1299

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ jobs:
run: |
make -s version | tr -d '\n' > VERSION
shell: sh

- name: Install and initialize swagger
run: |
go install github.com/swaggo/swag/cmd/swag@latest
swag init
shell: sh

- name: golangci-lint
uses: golangci/golangci-lint-action@v4
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,4 @@ debian/aptly-dbg.debhelper.log
debian/aptly-dbg.substvars
debian/aptly-dbg/

docs/
39 changes: 37 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ all: prepare test bench check system-test

prepare: ## Install go module dependencies
go mod download
# install and initialize swagger
go install github.com/swaggo/swag/cmd/swag@latest
PATH=$(BINPATH)/:$(PATH) swag init
go mod verify
go mod tidy -v
go generate
Expand Down Expand Up @@ -48,6 +51,7 @@ ifeq ($(RUN_LONG_TESTS), yes)
go generate
test -d /srv/etcd || system/t13_etcd/install-etcd.sh
system/t13_etcd/start-etcd.sh &
# build coverage binary
go test -v -coverpkg="./..." -c -tags testruncli
kill `cat /tmp/etcd.pid`

Expand All @@ -61,6 +65,10 @@ docker-test: ## Run system tests
@echo Building aptly.test ...
@rm -f aptly.test
go generate
# install and initialize swagger
go install github.com/swaggo/swag/cmd/swag@latest
PATH=$(BINPATH)/:$(PATH) swag init
# build coverage binary
go test -v -coverpkg="./..." -c -tags testruncli
@echo Running python tests ...
@test -e aws.creds && . ./aws.creds; \
Expand Down Expand Up @@ -112,32 +120,56 @@ releasetype: # Print release type (ci/release)
echo $$reltype

build: ## Build aptly
# install and initialize swagger
unset GOBIN; go install github.com/swaggo/swag/cmd/swag@latest
PATH=$(BINPATH)/:$(PATH) swag init
# prepare
go mod tidy
go generate
# build
go build -o build/aptly

dev-server: prepare ## Run dev-server
go install github.com/air-verse/air@v1.52.3
cp debian/aptly.conf /var/lib/aptly/.aptly.conf
sed -i /enableSwaggerEndpoint/s/false/true/ /var/lib/aptly/.aptly.conf
PATH=$(BINPATH):$$PATH air -build.pre_cmd 'swag init' -build.exclude_dir system -build.exclude_dir debian -build.exclude_dir docs -- api serve -listen 0.0.0.0:3142

dpkg: ## Build debian packages
@test -n "$(DEBARCH)" || (echo "please define DEBARCH"; exit 1)
# go generate
GOPATH=$$PWD/.go go generate -v
# install and initialize swagger
go install github.com/swaggo/swag/cmd/swag@latest
PATH=$(BINPATH)/:$(PATH) swag init
# set debian version
@if [ "`make -s releasetype`" = "ci" ]; then \
echo CI Build, setting version... ; \
cp debian/changelog debian/changelog.dpkg-bak ; \
DEBEMAIL="CI <ci@aptly>" dch -v `make -s version` "CI build" ; \
fi
# Run dpkg-buildpackage
buildtype="any" ; \
if [ "$(DEBARCH)" = "amd64" ]; then \
buildtype="any,all" ; \
fi ; \
echo Building: $$buildtype ; \
dpkg-buildpackage -us -uc --build=$$buildtype -d --host-arch=$(DEBARCH)
# cleanup
@test -f debian/changelog.dpkg-bak && mv debian/changelog.dpkg-bak debian/changelog || true ; \
mkdir -p build && mv ../*.deb build/ ; \
cd build && ls -l *.deb

binaries: ## Build binary releases (FreeBSD, MacOS, Linux tar)
@mkdir -p build/tmp/man build/tmp/completion/bash_completion.d build/tmp/completion/zsh/vendor-completions
# set version
@make version > VERSION
# install and initialize swagger
GOOS=linux GOARCH=amd64 go install github.com/swaggo/swag/cmd/swag@latest
PATH=$(BINPATH)/:$(PATH) swag init
# build aptly
GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o build/tmp/aptly -ldflags='-extldflags=-static'
# install
@mkdir -p build/tmp/man build/tmp/completion/bash_completion.d build/tmp/completion/zsh/vendor-completions
@cp man/aptly.1 build/tmp/man/
@cp completion.d/aptly build/tmp/completion/bash_completion.d/
@cp completion.d/_aptly build/tmp/completion/zsh/vendor-completions/
Expand Down Expand Up @@ -170,6 +202,9 @@ docker-unit-tests: ## Run unit tests in docker container
docker-system-tests: ## Run system tests in docker container (add TEST=t04_mirror to run only specific tests)
@docker run -it --rm -v ${PWD}:/app aptly-dev /app/system/run-system-tests $(TEST)

docker-dev-server: ## Run development server (auto recompiling) on http://localhost:3142
@docker run -it --rm -p 3142:3142 -v ${PWD}:/work/src aptly-dev /work/src/system/docker-wrapper dev-server

docker-lint: ## Run golangci-lint in docker container
@docker run -it --rm -v ${PWD}:/app -e GOLANGCI_LINT_VERSION=$(GOLANGCI_LINT_VERSION) aptly-dev /app/system/run-golangci-lint

Expand All @@ -183,4 +218,4 @@ clean: ## remove local build and module cache
test -d .go/ && chmod u+w -R .go/ && rm -rf .go/ || true
rm -rf build/ docs/ obj-*-linux-gnu*

.PHONY: help man prepare version binaries docker-release docker-system-tests docker-unit-tests docker-lint docker-build docker-image build docker-aptly clean releasetype dpkg
.PHONY: help man prepare version binaries docker-release docker-system-tests docker-unit-tests docker-lint docker-build docker-image build docker-aptly clean releasetype dpkg dev-server docker-dev-server
5 changes: 5 additions & 0 deletions api/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package api

type Error struct {
Error string `json:"error"`
}
7 changes: 6 additions & 1 deletion api/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ func verifyDir(c *gin.Context) bool {
return true
}

// GET /files
// @Summary Get files
// @Description Get list of uploaded files.
// @Tags Files
// @Produce json
// @Success 200 {array} string "List of files"
// @Router /api/files [get]
func apiFilesListDirs(c *gin.Context) {
list := []string{}
listLock := &sync.Mutex{}
Expand Down
94 changes: 88 additions & 6 deletions api/mirror.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ func getVerifier(keyRings []string) (pgp.Verifier, error) {
return verifier, nil
}

// GET /api/mirrors
// @Summary Get mirrors
// @Description Show list of currently available mirrors. Each mirror is returned as in “show” API.
// @Tags Mirrors
// @Produce json
// @Success 200 {array} deb.RemoteRepo
// @Router /api/mirrors [get]
func apiMirrorsList(c *gin.Context) {
collectionFactory := context.NewCollectionFactory()
collection := collectionFactory.RemoteRepoCollection()
Expand All @@ -45,7 +50,27 @@ func apiMirrorsList(c *gin.Context) {
c.JSON(200, result)
}

// POST /api/mirrors
// @Summary Create mirror
// @Description Create empty mirror with specified parameters.
// @Tags Mirrors
// @Accept json
// @Produce json
// @Param Name query string true "mirror name"
// @Param ArchiveURL query string true "url of the archive to mirror e.g. http://deb.debian.org/debian/"
// @Param Distribution query string false "distribution name to mirror e.g. `buster`, for flat repositories use `./` instead of distribution name"
// @Param Filter query string false "package query that is applied to packages in the mirror"
// @Param Components query []string false "components to mirror, if not specified aptly would fetch all components"
// @Param Architectures query []string false "limit mirror to those architectures, if not specified aptly would fetch all architectures"
// @Param Keyrings query []string false "gpg keyring(s) to use when verifying `Release` file"
// @Param DownloadSources query bool false "whether to mirror sources"
// @Param DownloadUdebs query bool false "whether to mirror `.udeb` packages (Debian installer support)"
// @Param DownloadInstaller query bool false "whether to download additional not packaged installer files"
// @Param FilterWithDeps query bool false "when filtering, include dependencies of matching packages as well"
// @Param SkipComponentCheck query bool false "whether to skip if the given components are in the `Release` file"
// @Param IgnoreSignatures query bool false "whether to skip the verification of `Release` file signatures"
// @Success 200 {object} deb.RemoteRepo
// @Failure 400 {object} Error "Bad Request"
// @Router /api/mirrors [post]
func apiMirrorsCreate(c *gin.Context) {
var err error
var b struct {
Expand Down Expand Up @@ -129,7 +154,18 @@ func apiMirrorsCreate(c *gin.Context) {
c.JSON(201, repo)
}

// DELETE /api/mirrors/:name
// @Summary Delete Mirror
// @Description Delete a mirror
// @Tags Mirrors
// @Consume json
// @Produce json
// @Param name path string true "mirror name"
// @Param force query int true "force: 1 to enable"
// @Success 200 {object} task.ProcessReturnValue
// @Failure 404 {object} Error "Mirror not found"
// @Failure 403 {object} Error "Unable to delete mirror with snapshots"
// @Failure 500 {object} Error "Unable to delete"
// @Router /api/mirrors/{name} [delete]
func apiMirrorsDrop(c *gin.Context) {
name := c.Params.ByName("name")
force := c.Request.URL.Query().Get("force") == "1"
Expand Down Expand Up @@ -168,7 +204,16 @@ func apiMirrorsDrop(c *gin.Context) {
})
}

// GET /api/mirrors/:name
// @Summary Show Mirror
// @Description Get mirror information by name
// @Tags Mirrors
// @Consume json
// @Produce json
// @Param name path string true "mirror name"
// @Success 200 {object} deb.RemoteRepo
// @Failure 404 {object} Error "Mirror not found"
// @Failure 500 {object} Error "Internal Error"
// @Router /api/mirrors/{name} [get]
func apiMirrorsShow(c *gin.Context) {
collectionFactory := context.NewCollectionFactory()
collection := collectionFactory.RemoteRepoCollection()
Expand All @@ -188,7 +233,19 @@ func apiMirrorsShow(c *gin.Context) {
c.JSON(200, repo)
}

// GET /api/mirrors/:name/packages
// @Summary List Mirror Packages
// @Description Get a list of packages from a mirror
// @Tags Mirrors
// @Consume json
// @Produce json
// @Param name path string true "mirror name"
// @Param q query string false "search query"
// @Param format query string false "format: `details` for more detailed information"
// @Success 200 {array} deb.Package "List of Packages"
// @Failure 400 {object} Error "Unable to determine list of architectures"
// @Failure 404 {object} Error "Mirror not found"
// @Failure 500 {object} Error "Internal Error"
// @Router /api/mirrors/{name}/packages [get]
func apiMirrorsPackages(c *gin.Context) {
collectionFactory := context.NewCollectionFactory()
collection := collectionFactory.RemoteRepoCollection()
Expand Down Expand Up @@ -266,7 +323,32 @@ func apiMirrorsPackages(c *gin.Context) {
}
}

// PUT /api/mirrors/:name
// @Summary Update Mirror
// @Description Update Mirror and download packages
// @Tags Mirrors
// @Consume json
// @Produce json
// @Param name path string true "mirror name to update"
// @Param Name query string false "change mirror name"
// @Param ArchiveURL query string false "ArchiveURL"
// @Param Filter query string false "Filter"
// @Param Architectures query []string false "Architectures"
// @Param Components query []string false "Components"
// @Param Keyrings query []string false "Keyrings"
// @Param FilterWithDeps query bool false "FilterWithDeps"
// @Param DownloadSources query bool false "DownloadSources"
// @Param DownloadUdebs query bool false "DownloadUdebs"
// @Param SkipComponentCheck query bool false "SkipComponentCheck"
// @Param IgnoreChecksums query bool false "IgnoreChecksums"
// @Param IgnoreSignatures query bool false "IgnoreSignatures"
// @Param ForceUpdate query bool false "ForceUpdate"
// @Param SkipExistingPackages query bool false "SkipExistingPackages"
// @Success 200 {object} task.ProcessReturnValue "Mirror was updated successfully"
// @Success 202 {object} task.Task "Mirror is being updated"
// @Failure 400 {object} Error "Unable to determine list of architectures"
// @Failure 404 {object} Error "Mirror not found"
// @Failure 500 {object} Error "Internal Error"
// @Router /api/mirrors/{name} [put]
func apiMirrorsUpdate(c *gin.Context) {
var (
err error
Expand Down
10 changes: 9 additions & 1 deletion api/packages.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,15 @@ func apiPackagesShow(c *gin.Context) {
c.JSON(200, p)
}

// GET /api/packages
// @Summary Get packages
// @Description Get list of packages.
// @Tags Packages
// @Consume json
// @Produce json
// @Param q query string false "search query"
// @Param format query string false "format: `details` for more detailed information"
// @Success 200 {array} string "List of packages"
// @Router /api/packages [get]
func apiPackages(c *gin.Context) {
collectionFactory := context.NewCollectionFactory()
collection := collectionFactory.PackageCollection()
Expand Down
7 changes: 6 additions & 1 deletion api/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,12 @@ func parseEscapedPath(path string) string {
return result
}

// GET /publish
// @Summary Get publish points
// @Description Get list of available publish points. Each publish point is returned as in “show” API.
// @Tags Publish
// @Produce json
// @Success 200 {array} deb.PublishedRepo
// @Router /api/publish [get]
func apiPublishList(c *gin.Context) {
collectionFactory := context.NewCollectionFactory()
collection := collectionFactory.PublishedRepoCollection()
Expand Down
45 changes: 42 additions & 3 deletions api/repos.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ func reposServeInAPIMode(c *gin.Context) {
c.FileFromFS(pkgpath, http.Dir(publicPath))
}

// GET /api/repos
// @Summary Get repos
// @Description Get list of available repos. Each repo is returned as in “show” API.
// @Tags Repos
// @Produce json
// @Success 200 {array} deb.LocalRepo
// @Router /api/repos [get]
func apiReposList(c *gin.Context) {
result := []*deb.LocalRepo{}

Expand All @@ -64,7 +69,18 @@ func apiReposList(c *gin.Context) {
c.JSON(200, result)
}

// POST /api/repos
// @Summary Create repository
// @Description Create a local repository.
// @Tags Repos
// @Produce json
// @Consume json
// @Param Name query string false "Name of repository to be created."
// @Param Comment query string false "Text describing local repository, for the user"
// @Param DefaultDistribution query string false "Default distribution when publishing from this local repo"
// @Param DefaultComponent query string false "Default component when publishing from this local repo"
// @Success 201 {object} deb.LocalRepo
// @Failure 400 {object} Error "Repository already exists"
// @Router /api/repos [post]
func apiReposCreate(c *gin.Context) {
var b struct {
Name string `binding:"required"`
Expand Down Expand Up @@ -143,6 +159,14 @@ func apiReposEdit(c *gin.Context) {
}

// GET /api/repos/:name
// @Summary Get repository info by name
// @Description Returns basic information about local repository.
// @Tags Repos
// @Produce json
// @Param name path string true "Repository name"
// @Success 200 {object} deb.LocalRepo
// @Failure 404 {object} Error "Repository not found"
// @Router /api/repos/{name} [get]
func apiReposShow(c *gin.Context) {
collectionFactory := context.NewCollectionFactory()
collection := collectionFactory.LocalRepoCollection()
Expand Down Expand Up @@ -295,7 +319,22 @@ func apiReposPackageFromFile(c *gin.Context) {
apiReposPackageFromDir(c)
}

// POST /repos/:name/file/:dir
// @Summary Add packages from uploaded file/directory
// @Description Import packages from files (uploaded using File Upload API) to the local repository. If directory specified, aptly would discover package files automatically.
// @Description Adding same package to local repository is not an error.
// @Description By default aptly would try to remove every successfully processed file and directory `dir` (if it becomes empty after import).
// @Tags Repos
// @Param name path string true "Repository name"
// @Param dir path string true "Directory to add"
// @Consume json
// @Param noRemove query string false "when value is set to 1, don’t remove any files"
// @Param forceReplace query string false "when value is set to 1, remove packages conflicting with package being added (in local repository)"
// @Produce json
// @Success 200 {string} string "OK"
// @Failure 400 {object} Error "wrong file"
// @Failure 404 {object} Error "Repository not found"
// @Failure 500 {object} Error "Error adding files"
// @Router /api/repos/{name}/{dir} [post]
func apiReposPackageFromDir(c *gin.Context) {
forceReplace := c.Request.URL.Query().Get("forceReplace") == "1"
noRemove := c.Request.URL.Query().Get("noRemove") == "1"
Expand Down
Loading
Loading