golang Debian仓库管理工具插件库aptly的使用

Golang Debian仓库管理工具插件库aptly的使用

简介

Aptly是一个用于Debian仓库管理的多功能工具。

aptly logo

主要功能

  • 创建远程Debian/Ubuntu仓库的镜像,可按组件/架构进行限制
  • 在任何时间点对镜像创建快照,固定仓库在特定时间点的状态
  • 将快照发布为Debian仓库,供apt使用
  • 从上游镜像控制更新快照中的一个或多个包,跟踪依赖关系
  • 将两个或多个快照合并为一个
  • 按搜索查询过滤仓库,必要时拉取依赖项
  • 将自己制作的包发布为Debian仓库
  • 提供REST API进行远程访问

安装

Debian/Ubuntu系统

Aptly提供以下deb包:

  • aptly:包含主程序、手册页和shell补全
  • aptly-api:REST API的systemd服务,使用全局/etc/aptly.conf
  • aptly-dbg:用于调试的符号

上游Debian包安装

如果需要较新版本(不在Debian/Ubuntu官方仓库中),可以安装上游deb包:

  1. 安装APT密钥(以root身份):
wget -O /etc/apt/keyrings/aptly.asc https://www.aptly.info/pubkey.txt
  1. /etc/apt/sources.list.d/aptly.list中定义APT源:
deb [signed-by=/etc/apt/keyrings/aptly.asc] http://repo.aptly.info/release DIST main

其中DIST可以是:buster, bullseye, bookworm, focal, jammy, noble

  1. 安装aptly包:
apt-get update
apt-get install aptly
apt-get install aptly-api  # 安装REST API systemd服务

CI构建安装

要测试新功能或bug修复,可以安装CI构建(基于master构建,可能不稳定):

  1. /etc/apt/sources.list.d/aptly-ci.list中定义CI APT源:
deb [signed-by=/etc/apt/keyrings/aptly.asc] http://repo.aptly.info/ci DIST main

其中DIST同上

其他操作系统

二进制可执行文件(主要依赖libc)可从GitHub Releases获取,支持:

  • macOS/darwin (amd64, arm64)
  • FreeBSD (amd64, arm64, 386, arm)
  • 通用Linux (amd64, arm64, 386, arm)

基本使用示例

# 创建远程仓库镜像
aptly mirror create -architectures="amd64" buster-main http://deb.debian.org/debian buster main

# 更新镜像
aptly mirror update buster-main

# 创建快照
aptly snapshot create buster-main-$(date +%Y%m%d) from mirror buster-main

# 发布快照
aptly publish snapshot buster-main-$(date +%Y%m%d)

# 本地添加.deb包到仓库
aptly repo create local-repo
aptly repo add local-repo /path/to/deb/files/*.deb

# 创建并发布本地仓库快照
aptly snapshot create local-snap-$(date +%Y%m%d) from repo local-repo
aptly publish snapshot local-snap-$(date +%Y%m%d)

REST API使用示例

启动API服务:

aptly api serve

然后可以使用curl或其他HTTP客户端与API交互:

# 获取镜像列表
curl http://localhost:8080/api/mirrors

# 创建新镜像
curl -X POST -H "Content-Type: application/json" \
  -d '{"Name":"ubuntu-focal","ArchiveUrl":"http://archive.ubuntu.com/ubuntu/","Distribution":"focal","Components":["main","restricted"],"Architectures":["amd64"]}' \
  http://localhost:8080/api/mirrors/ubuntu-focal

最佳实践

  1. 定期更新镜像并创建快照
  2. 为每个重要变更创建新的快照
  3. 使用发布点来组织不同版本的软件包
  4. 考虑使用CI/CD流程自动化仓库管理
  5. 对生产环境使用稳定的发布版本,而非CI构建

更多关于golang Debian仓库管理工具插件库aptly的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang Debian仓库管理工具插件库aptly的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang中使用aptly管理Debian仓库

aptly是一个强大的Debian仓库管理工具,可以方便地创建、管理和发布Debian软件包仓库。下面我将介绍如何在Golang中使用aptly的API和命令行工具来管理Debian仓库。

安装aptly

首先需要在系统上安装aptly:

# 对于Debian/Ubuntu系统
sudo apt-get install aptly

# 或者使用官方提供的安装方法
sudo apt-key adv --keyserver keys.gnupg.net --recv-keys 2A194991
echo "deb http://repo.aptly.info/ squeeze main" | sudo tee -a /etc/apt/sources.list
sudo apt-get update
sudo apt-get install aptly

Golang中调用aptly API

aptly提供了REST API,我们可以通过Golang的HTTP客户端与之交互。下面是一个基本示例:

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
)

const aptlyAPI = "http://localhost:8080/api"

// 创建新的仓库
func createRepo(repoName string) error {
	data := map[string]string{
		"Name":        repoName,
		"DefaultDistribution": "stable",
		"DefaultComponent":   "main",
	}
	jsonData, _ := json.Marshal(data)

	resp, err := http.Post(aptlyAPI+"/repos", "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusCreated {
		body, _ := ioutil.ReadAll(resp.Body)
		return fmt.Errorf("failed to create repo: %s", string(body))
	}

	return nil
}

// 列出所有仓库
func listRepos() ([]string, error) {
	resp, err := http.Get(aptlyAPI + "/repos")
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var repos []struct {
		Name string `json:"Name"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&repos); err != nil {
		return nil, err
	}

	var repoNames []string
	for _, repo := range repos {
		repoNames = append(repoNames, repo.Name)
	}

	return repoNames, nil
}

func main() {
	// 创建新仓库
	if err := createRepo("my-repo"); err != nil {
		fmt.Printf("Error creating repo: %v\n", err)
	}

	// 列出所有仓库
	repos, err := listRepos()
	if err != nil {
		fmt.Printf("Error listing repos: %v\n", err)
	} else {
		fmt.Println("Available repositories:")
		for _, repo := range repos {
			fmt.Println("-", repo)
		}
	}
}

使用命令行工具

如果不想使用API,也可以在Golang中直接调用aptly命令行工具:

package main

import (
	"fmt"
	"os/exec"
)

// 使用aptly命令行工具创建仓库
func createRepoCLI(repoName string) error {
	cmd := exec.Command("aptly", "repo", "create", "-distribution=stable", "-component=main", repoName)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to create repo: %v, output: %s", err, string(output))
	}
	return nil
}

// 添加deb包到仓库
func addPackageToRepo(repoName, debPath string) error {
	cmd := exec.Command("aptly", "repo", "add", repoName, debPath)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to add package: %v, output: %s", err, string(output))
	}
	return nil
}

// 发布仓库
func publishRepo(repoName, publishDir string) error {
	cmd := exec.Command("aptly", "publish", "repo", "-architectures=amd64,i386", repoName, publishDir)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to publish repo: %v, output: %s", err, string(output))
	}
	return nil
}

func main() {
	repoName := "my-go-repo"
	debPath := "./example-package.deb"
	publishDir := "/var/www/html/debian"

	if err := createRepoCLI(repoName); err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	if err := addPackageToRepo(repoName, debPath); err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	if err := publishRepo(repoName, publishDir); err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	fmt.Println("Repository created and published successfully!")
}

高级功能示例

aptly还支持镜像上游仓库、快照管理等功能:

// 创建上游仓库镜像
func createMirror(name, url, distribution string) error {
	cmd := exec.Command("aptly", "mirror", "create", 
		"-architectures=amd64,i386", 
		name, url, distribution)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to create mirror: %v, output: %s", err, string(output))
	}
	return nil
}

// 更新镜像
func updateMirror(name string) error {
	cmd := exec.Command("aptly", "mirror", "update", name)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to update mirror: %v, output: %s", err, string(output))
	}
	return nil
}

// 创建快照
func createSnapshotFromRepo(repoName, snapshotName string) error {
	cmd := exec.Command("aptly", "snapshot", "create", snapshotName, "from", "repo", repoName)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to create snapshot: %v, output: %s", err, string(output))
	}
	return nil
}

总结

aptly是一个功能强大的Debian仓库管理工具,通过Golang可以:

  1. 直接调用其REST API进行管理
  2. 通过exec包调用命令行工具
  3. 实现自动化仓库管理流程

在实际使用中,建议:

  • 对于简单任务,使用命令行方式更直接
  • 对于复杂集成,使用API方式更灵活
  • 注意错误处理和日志记录
  • 考虑添加适当的权限控制

以上代码示例展示了aptly的基本用法,你可以根据实际需求进行扩展和修改。

回到顶部