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

Improve/documentation #1359

Merged
merged 38 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
ba86851
add api documentation stubs
neolynx Oct 3, 2024
cc1fc7c
allow comments in config file
neolynx Oct 3, 2024
2df82e8
document aptly.conf
neolynx Oct 4, 2024
69a1e25
docs: improve swagger
neolynx Oct 5, 2024
e677a2e
go mod tidy
neolynx Oct 4, 2024
096fa47
update doc
neolynx Oct 15, 2024
9b8f6b1
fix conflict
neolynx Nov 1, 2024
c055611
update go.mod
neolynx Nov 1, 2024
8f8de4b
update
neolynx Nov 2, 2024
2171c05
fix lint
neolynx Nov 3, 2024
a5f8ce2
doc: import chapters from aptly.info
neolynx Nov 3, 2024
74bc3f5
update go.mod
neolynx Nov 17, 2024
9fc7ebd
Update repos, task, snapshot api docs
iofq Nov 17, 2024
398fec1
Update packages api docs
iofq Nov 19, 2024
68fe2bc
Update gpg, graph api docs
iofq Nov 19, 2024
3992180
Update db api docs
iofq Nov 19, 2024
d5571c4
Update files api docs
iofq Nov 19, 2024
397362b
fix swagger build
neolynx Nov 21, 2024
83f7c86
doc: improve cmd usage arguments
neolynx Nov 28, 2024
4f229a5
update doc
neolynx Nov 28, 2024
a69c00a
swagger: improve layout
neolynx Nov 28, 2024
63b8cc9
dos: improve api info
neolynx Nov 28, 2024
abfad37
swagger: cleanup files doc
neolynx Nov 28, 2024
4ff3c89
swagger: cleanup Snapshots
neolynx Nov 28, 2024
a59fc6b
swwagger: cleanup
neolynx Nov 28, 2024
75e5f95
task-dummy: remove internal testing API
neolynx Nov 28, 2024
c6e0a06
swagger: cleanup
neolynx Nov 28, 2024
e5e3c49
swagger: document async
neolynx Nov 28, 2024
d8b9777
swagger: document params
neolynx Nov 28, 2024
1f469e2
fix optional params
neolynx Nov 29, 2024
622072b
document aptly.conf
neolynx Nov 29, 2024
ea80f6d
write commented json default config
neolynx Dec 1, 2024
09c5634
fix json
neolynx Dec 2, 2024
1301847
update CONTRIBUTING
neolynx Dec 3, 2024
3d8968e
swagger: install native swag
neolynx Dec 3, 2024
280563c
unit-tests: allow running as user
neolynx Dec 3, 2024
e92afd8
fix unit tests on arm
neolynx Dec 3, 2024
e319f3c
update doc
neolynx Dec 11, 2024
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
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,7 @@ usr/bin/aptly
dpkgs/
debian/changelog.dpkg-bak

docs/
docs/docs.go
docs/swagger.json
docs/swagger.yaml
docs/swagger.conf
60 changes: 12 additions & 48 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,13 @@ make docker-build

To run aptly commands in the development docker container, run:
```
make docker-aptly
make docker-shell
```

Example:
```
$ make docker-aptly
bash: cannot set terminal process group (16): Inappropriate ioctl for device
bash: no job control in this shell
aptly@b43e8473ef81:/app$ aptly version
$ make docker-shell
aptly@b43e8473ef81:/work/src$ aptly version
aptly version: 1.5.0+189+g0fc90dff
```

Expand Down Expand Up @@ -152,41 +150,27 @@ Run `make help` for more information.

This section describes local setup to start contributing to aptly.

#### Go & Python

You would need `Go` (latest version is recommended) and `Python` 3.9 (or newer, the CI currently tests against 3.11).

If you're new to Go, follow [getting started guide](https://golang.org/doc/install) to install it and perform
initial setup. With Go 1.8+, default `$GOPATH` is `$HOME/go`, so rest of this document assumes that.

Usually `$GOPATH/bin` is appended to your `$PATH` to make it easier to run built binaries, but you might choose
to prepend it or to skip this test if you're security conscious.

#### Dependencies

You would need some additional tools and Python virtual environment to run tests and checks, install them with:
Building aptly requires go version 1.22.

make prepare dev system/env
On Debian bookworm with backports enabled, go can be installed with:

This is usually one-time action.

Aptly is using Go modules to manage dependencies, download modules using:

make modules
apt install -t bookworm-backports golang-go

#### Building

If you want to build aptly binary from your current source tree, run:
To build aptly, run:

make install
make build

This would build `aptly` in `$GOPATH/bin`, so depending on your `$PATH`, you should be able to run it immediately with:
Run aptly:

aptly
build/aptly

Or, if it's not on your path:
To install aptly into `$GOPATH/bin`, run:

~/go/bin/aptly
make install

#### Unit-tests

Expand Down Expand Up @@ -244,26 +228,6 @@ There are some packages available under `system/files/` directory which are used
this default location. You can run aptly under different user or by using non-default config location with non-default
aptly root directory.

#### Style Checks

Style checks could be run with:

make check

aptly is using [golangci-lint](https://github.com/golangci/golangci-lint) to run style checks on Go code. Configuration
for the linter could be found in [.golangci.yml](.golangci.yml) file.

Python code (system tests) are linted with [flake8 tool](https://pypi.python.org/pypi/flake8).

#### Vendored Code

aptly is using Go vendoring for all the libraries aptly depends upon. `vendor/` directory is checked into the source
repository to avoid any problems if source repositories go away. Go build process will automatically prefer vendored
packages over packages in `$GOPATH`.

If you want to update vendored dependencies or to introduce new dependency, use [dep tool](https://github.com/golang/dep).
Usually all you need is `dep ensure` or `dep ensure -update`.

### man Page

aptly is using combination of [Go templates](http://godoc.org/text/template) and automatically generated text to build `aptly.1` man page. If either source
Expand Down
24 changes: 15 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ version: ## Print aptly version

swagger-install:
# Install swag
@test -f $(BINPATH)/swag || GOOS=linux GOARCH=amd64 go install github.com/swaggo/swag/cmd/swag@latest
@test -f $(BINPATH)/swag || GOOS= GOARCH= go install github.com/swaggo/swag/cmd/swag@latest
# Generate swagger.conf
cp docs/swagger.conf.tpl docs/swagger.conf
echo "// @version $(VERSION)" >> docs/swagger.conf

azurite-start:
azurite & \
Expand All @@ -55,16 +58,16 @@ azurite-stop:

swagger: swagger-install
# Generate swagger docs
@PATH=$(BINPATH)/:$(PATH) swag init --markdownFiles docs
@PATH=$(BINPATH)/:$(PATH) swag init --parseDependency --parseInternal --markdownFiles docs --generalInfo docs/swagger.conf

etcd-install:
# Install etcd
test -d /srv/etcd || system/t13_etcd/install-etcd.sh
test -d /tmp/aptly-etcd || system/t13_etcd/install-etcd.sh

flake8: ## run flake8 on system test python files
flake8 system/

lint:
lint: prepare
# Install golangci-lint
@test -f $(BINPATH)/golangci-lint || go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION)
# Running lint
Expand All @@ -76,17 +79,19 @@ build: prepare swagger ## Build aptly

install:
@echo "\e[33m\e[1mBuilding aptly ...\e[0m"
go generate
# go generate
@go generate
# go install -v
@out=`mktemp`; if ! go install -v > $$out 2>&1; then cat $$out; rm -f $$out; echo "\nBuild failed\n"; exit 1; else rm -f $$out; fi

test: prepare swagger etcd-install ## Run unit tests
@echo "\e[33m\e[1mStarting etcd ...\e[0m"
@mkdir -p /tmp/etcd-data; system/t13_etcd/start-etcd.sh > /tmp/etcd-data/etcd.log 2>&1 &
@mkdir -p /tmp/aptly-etcd-data; system/t13_etcd/start-etcd.sh > /tmp/aptly-etcd-data/etcd.log 2>&1 &
@echo "\e[33m\e[1mRunning go test ...\e[0m"
go test -v ./... -gocheck.v=true -coverprofile=unit.out; echo $$? > .unit-test.ret
@echo "\e[33m\e[1mStopping etcd ...\e[0m"
@pid=`cat /tmp/etcd.pid`; kill $$pid
@rm -f /tmp/etcd-data/etcd.log
@rm -f /tmp/aptly-etcd-data/etcd.log
@ret=`cat .unit-test.ret`; if [ "$$ret" = "0" ]; then echo "\n\e[32m\e[1mUnit Tests SUCCESSFUL\e[0m"; else echo "\n\e[31m\e[1mUnit Tests FAILED\e[0m"; fi; rm -f .unit-test.ret; exit $$ret

system-test: prepare swagger etcd-install ## Run system tests
Expand All @@ -107,7 +112,7 @@ serve: prepare swagger-install ## Run development server (auto recompiling)
test -f $(BINPATH)/air || go install github.com/air-verse/[email protected]
cp debian/aptly.conf ~/.aptly.conf
sed -i /enableSwaggerEndpoint/s/false/true/ ~/.aptly.conf
PATH=$(BINPATH):$$PATH air -build.pre_cmd 'swag init -q --markdownFiles docs' -build.exclude_dir docs,system,debian,pgp/keyrings,pgp/test-bins,completion.d,man,deb/testdata,console,_man,systemd,obj-x86_64-linux-gnu -- api serve -listen 0.0.0.0:3142
PATH=$(BINPATH):$$PATH air -build.pre_cmd 'swag init -q --markdownFiles docs --generalInfo docs/swagger.conf' -build.exclude_dir docs,system,debian,pgp/keyrings,pgp/test-bins,completion.d,man,deb/testdata,console,_man,systemd,obj-x86_64-linux-gnu -- api serve -listen 0.0.0.0:3142

dpkg: prepare swagger ## Build debian packages
@test -n "$(DEBARCH)" || (echo "please define DEBARCH"; exit 1)
Expand Down Expand Up @@ -205,7 +210,8 @@ man: ## Create man pages

clean: ## remove local build and module cache
# Clean all generated and build files
test -d .go/ && chmod u+w -R .go/ && rm -rf .go/ || true
find .go/ -type d ! -perm -u=w -exec chmod u+w {} \;
rm -rf .go/
rm -rf build/ obj-*-linux-gnu* tmp/
rm -f unit.out aptly.test VERSION docs/docs.go docs/swagger.json docs/swagger.yaml docs/swagger.conf
find system/ -type d -name __pycache__ -exec rm -rf {} \; 2>/dev/null || true
Expand Down
45 changes: 42 additions & 3 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,43 @@ import (
// 3. SnapshotCollection
// 4. PublishedRepoCollection

// GET /api/version
type aptlyVersion struct {
// Aptly Version
Version string `json:"Version"`
}

// @Summary Aptly Version
// @Description **Get aptly version**
// @Description
// @Description **Example:**
// @Description ```
// @Description $ curl http://localhost:8080/api/version
// @Description {"Version":"0.9~dev"}
// @Description ```
// @Tags Status
// @Produce json
// @Success 200 {object} aptlyVersion
// @Router /api/version [get]
func apiVersion(c *gin.Context) {
c.JSON(200, gin.H{"Version": aptly.Version})
}

// GET /api/ready
type aptlyStatus struct {
// Aptly Status
Status string `json:"Status" example:"'Aptly is ready', 'Aptly is unavailable', 'Aptly is healthy'"`
}

// @Summary Get Ready State
// @Description **Get aptly ready state**
// @Description
// @Description Return aptly ready state:
// @Description - `Aptly is ready` (HTTP 200)
// @Description - `Aptly is unavailable` (HTTP 503)
// @Tags Status
// @Produce json
// @Success 200 {object} aptlyStatus "Aptly is ready"
// @Failure 503 {object} aptlyStatus "Aptly is unavailable"
// @Router /api/ready [get]
func apiReady(isReady *atomic.Value) func(*gin.Context) {
return func(c *gin.Context) {
if isReady == nil || !isReady.Load().(bool) {
Expand All @@ -40,7 +71,15 @@ func apiReady(isReady *atomic.Value) func(*gin.Context) {
}
}

// GET /api/healthy
// @Summary Get Health State
// @Description **Get aptly health state**
// @Description
// @Description Return aptly health state:
// @Description - `Aptly is healthy` (HTTP 200)
// @Tags Status
// @Produce json
// @Success 200 {object} aptlyStatus
// @Router /api/healthy [get]
func apiHealthy(c *gin.Context) {
c.JSON(200, gin.H{"Status": "Aptly is healthy"})
}
Expand Down
12 changes: 10 additions & 2 deletions api/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,17 @@ import (
"github.com/gin-gonic/gin"
)

// POST /api/db/cleanup
// @Summary DB Cleanup
// @Description **Cleanup Aptly DB**
// @Description Database cleanup removes information about unreferenced packages and deletes files in the package pool that aren’t used by packages anymore.
// @Description It is a good idea to run this command after massive deletion of mirrors, snapshots or local repos.
// @Tags Database
// @Produce json
// @Param _async query bool false "Run in background and return task object"
// @Success 200 {object} string "Output"
// @Failure 404 {object} Error "Not Found"
// @Router /api/db/cleanup [post]
func apiDbCleanup(c *gin.Context) {

resources := []string{string(task.AllResourcesKey)}
maybeRunTaskInBackground(c, "Clean up db", resources, func(out aptly.Progress, detail *task.Detail) (*task.ProcessReturnValue, error) {
var err error
Expand Down
83 changes: 75 additions & 8 deletions api/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,16 @@ func verifyDir(c *gin.Context) bool {
return true
}

// @Summary Get files
// @Description Get list of uploaded files.
// @Summary List Directories
// @Description **Get list of upload directories**
// @Description
// @Description **Example:**
// @Description ```
// @Description $ curl http://localhost:8080/api/files
// @Description ["aptly-0.9"]
// @Description ```
// @Tags Files
// @Produce json
// @Produce json
// @Success 200 {array} string "List of files"
// @Router /api/files [get]
func apiFilesListDirs(c *gin.Context) {
Expand Down Expand Up @@ -67,7 +73,27 @@ func apiFilesListDirs(c *gin.Context) {
c.JSON(200, list)
}

// POST /files/:dir/
// @Summary Upload Files
// @Description **Upload files to a directory**
// @Description
// @Description - one or more files can be uploaded
// @Description - existing uploaded are overwritten
// @Description
// @Description **Example:**
// @Description ```
// @Description $ curl -X POST -F file=@aptly_0.9~dev+217+ge5d646c_i386.deb http://localhost:8080/api/files/aptly-0.9
// @Description ["aptly-0.9/aptly_0.9~dev+217+ge5d646c_i386.deb"]
// @Description ```
// @Tags Files
// @Accept multipart/form-data
// @Param dir path string true "Directory to upload files to. Created if does not exist"
// @Param files formData file true "Files to upload"
// @Produce json
// @Success 200 {array} string "list of uploaded files"
// @Failure 400 {object} Error "Bad Request"
// @Failure 404 {object} Error "Not Found"
// @Failure 500 {object} Error "Internal Server Error"
// @Router /api/files/{dir} [post]
func apiFilesUpload(c *gin.Context) {
if !verifyDir(c) {
return
Expand Down Expand Up @@ -118,10 +144,23 @@ func apiFilesUpload(c *gin.Context) {

apiFilesUploadedCounter.WithLabelValues(c.Params.ByName("dir")).Inc()
c.JSON(200, stored)

}

// GET /files/:dir
// @Summary List Files
// @Description **Show uploaded files in upload directory**
// @Description
// @Description **Example:**
// @Description ```
// @Description $ curl http://localhost:8080/api/files/aptly-0.9
// @Description ["aptly_0.9~dev+217+ge5d646c_i386.deb"]
// @Description ```
// @Tags Files
// @Produce json
// @Param dir path string true "Directory to list"
// @Success 200 {array} string "Files found in directory"
// @Failure 404 {object} Error "Not Found"
// @Failure 500 {object} Error "Internal Server Error"
// @Router /api/files/{dir} [get]
func apiFilesListFiles(c *gin.Context) {
if !verifyDir(c) {
return
Expand Down Expand Up @@ -159,7 +198,20 @@ func apiFilesListFiles(c *gin.Context) {
c.JSON(200, list)
}

// DELETE /files/:dir
// @Summary Delete Directory
// @Description **Delete upload directory and uploaded files within**
// @Description
// @Description **Example:**
// @Description ```
// @Description $ curl -X DELETE http://localhost:8080/api/files/aptly-0.9
// @Description {}
// @Description ```
// @Tags Files
// @Produce json
// @Param dir path string true "Directory"
// @Success 200 {object} string "msg"
// @Failure 500 {object} Error "Internal Server Error"
// @Router /api/files/{dir} [delete]
func apiFilesDeleteDir(c *gin.Context) {
if !verifyDir(c) {
return
Expand All @@ -174,7 +226,22 @@ func apiFilesDeleteDir(c *gin.Context) {
c.JSON(200, gin.H{})
}

// DELETE /files/:dir/:name
// @Summary Delete File
// @Description **Delete a uploaded file in upload directory**
// @Description
// @Description **Example:**
// @Description ```
// @Description $ curl -X DELETE http://localhost:8080/api/files/aptly-0.9/aptly_0.9~dev+217+ge5d646c_i386.deb
// @Description {}
// @Description ```
// @Tags Files
// @Produce json
// @Param dir path string true "Directory to delete from"
// @Param name path string true "File to delete"
// @Success 200 {object} string "msg"
// @Failure 400 {object} Error "Bad Request"
// @Failure 500 {object} Error "Internal Server Error"
// @Router /api/files/{dir}/{name} [delete]
func apiFilesDeleteFile(c *gin.Context) {
if !verifyDir(c) {
return
Expand Down
Loading
Loading