Добавление логирования
Добавления возможности использования github токена
This commit is contained in:
@@ -43,4 +43,12 @@ reposBaseDir = "/var/cache/alr-updater"
|
|||||||
log_file = "/var/log/alr-updater.log"
|
log_file = "/var/log/alr-updater.log"
|
||||||
# Максимальный размер файла логов в байтах (по умолчанию 100MB)
|
# Максимальный размер файла логов в байтах (по умолчанию 100MB)
|
||||||
# При достижении этого размера файл будет ротирован
|
# При достижении этого размера файл будет ротирован
|
||||||
max_size = 104857600
|
max_size = 104857600
|
||||||
|
|
||||||
|
[github]
|
||||||
|
# GitHub Personal Access Token для увеличения лимита API запросов
|
||||||
|
# Без токена: 60 запросов/час
|
||||||
|
# С токеном: 5000 запросов/час
|
||||||
|
# Создать токен: https://github.com/settings/tokens
|
||||||
|
# Требуемые права: public_repo (или repo для приватных репозиториев)
|
||||||
|
token = "CHANGE ME"
|
@@ -44,30 +44,88 @@ var (
|
|||||||
ErrIncorrectPassword = errors.New("incorrect password")
|
ErrIncorrectPassword = errors.New("incorrect password")
|
||||||
)
|
)
|
||||||
|
|
||||||
var httpModule = &starlarkstruct.Module{
|
func newHTTPModule(cfg *config.Config) *starlarkstruct.Module {
|
||||||
Name: "http",
|
return &starlarkstruct.Module{
|
||||||
Members: starlark.StringDict{
|
Name: "http",
|
||||||
"get": starlark.NewBuiltin("http.get", httpGet),
|
Members: starlark.StringDict{
|
||||||
"post": starlark.NewBuiltin("http.post", httpPost),
|
"get": httpGetWithConfig(cfg),
|
||||||
"put": starlark.NewBuiltin("http.put", httpPut),
|
"post": httpPostWithConfig(cfg),
|
||||||
"head": starlark.NewBuiltin("http.head", httpHead),
|
"put": httpPutWithConfig(cfg),
|
||||||
},
|
"head": httpHeadWithConfig(cfg),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func httpGet(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
func httpGetWithConfig(cfg *config.Config) *starlark.Builtin {
|
||||||
return makeRequest("http.get", http.MethodGet, args, kwargs, thread)
|
return starlark.NewBuiltin("http.get", func(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
return makeRequestWithConfig("http.get", http.MethodGet, args, kwargs, thread, cfg)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func httpPost(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
func httpPostWithConfig(cfg *config.Config) *starlark.Builtin {
|
||||||
return makeRequest("http.post", http.MethodPost, args, kwargs, thread)
|
return starlark.NewBuiltin("http.post", func(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
return makeRequestWithConfig("http.post", http.MethodPost, args, kwargs, thread, cfg)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func httpPut(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
func httpPutWithConfig(cfg *config.Config) *starlark.Builtin {
|
||||||
return makeRequest("http.put", http.MethodPut, args, kwargs, thread)
|
return starlark.NewBuiltin("http.put", func(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
return makeRequestWithConfig("http.put", http.MethodPut, args, kwargs, thread, cfg)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func httpHead(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
func httpHeadWithConfig(cfg *config.Config) *starlark.Builtin {
|
||||||
return makeRequest("http.head", http.MethodHead, args, kwargs, thread)
|
return starlark.NewBuiltin("http.head", func(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
return makeRequestWithConfig("http.head", http.MethodHead, args, kwargs, thread, cfg)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeRequestWithConfig(name, method string, args starlark.Tuple, kwargs []starlark.Tuple, thread *starlark.Thread, cfg *config.Config) (starlark.Value, error) {
|
||||||
|
var (
|
||||||
|
url string
|
||||||
|
redirect = true
|
||||||
|
headers = &starlarkHeaders{}
|
||||||
|
body = newBodyReader()
|
||||||
|
)
|
||||||
|
err := starlark.UnpackArgs(name, args, kwargs, "url", &url, "redirect??", &redirect, "headers??", headers, "body??", body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest(method, url, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Устанавливаем заголовки из аргументов
|
||||||
|
if headers.Header != nil {
|
||||||
|
req.Header = headers.Header
|
||||||
|
}
|
||||||
|
|
||||||
|
// Добавляем GitHub токен для запросов к api.github.com
|
||||||
|
if cfg.GitHub.Token != "" && strings.Contains(url, "api.github.com") {
|
||||||
|
req.Header.Set("Authorization", "token "+cfg.GitHub.Token)
|
||||||
|
}
|
||||||
|
|
||||||
|
client := http.DefaultClient
|
||||||
|
if !redirect {
|
||||||
|
client = &http.Client{
|
||||||
|
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||||
|
return http.ErrUseLastResponse
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("Making HTTP request").Str("url", url).Str("method", req.Method).Bool("redirect", redirect).Stringer("pos", thread.CallFrame(1).Pos).Send()
|
||||||
|
|
||||||
|
res, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("Got HTTP response").Str("host", res.Request.URL.Host).Int("code", res.StatusCode).Stringer("pos", thread.CallFrame(1).Pos).Send()
|
||||||
|
|
||||||
|
return starlarkResponse(res), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type starlarkBodyReader struct {
|
type starlarkBodyReader struct {
|
||||||
|
@@ -38,7 +38,7 @@ type Options struct {
|
|||||||
func Register(sd starlark.StringDict, opts *Options) {
|
func Register(sd starlark.StringDict, opts *Options) {
|
||||||
sd["run_every"] = runEveryModule
|
sd["run_every"] = runEveryModule
|
||||||
sd["sleep"] = starlark.NewBuiltin("sleep", sleep)
|
sd["sleep"] = starlark.NewBuiltin("sleep", sleep)
|
||||||
sd["http"] = httpModule
|
sd["http"] = newHTTPModule(opts.Config)
|
||||||
sd["regex"] = regexModule
|
sd["regex"] = regexModule
|
||||||
sd["store"] = storeModule(opts.DB, opts.Name)
|
sd["store"] = storeModule(opts.DB, opts.Name)
|
||||||
sd["updater"] = updaterModule(opts.Config)
|
sd["updater"] = updaterModule(opts.Config)
|
||||||
|
@@ -178,6 +178,15 @@ func runScheduled(thread *starlark.Thread, fn *starlark.Function, duration strin
|
|||||||
tickerMtx.Unlock()
|
tickerMtx.Unlock()
|
||||||
log.Debug("Created new scheduled ticker").Int("handle", handle).Str("duration", duration).Stringer("pos", thread.CallFrame(1).Pos).Send()
|
log.Debug("Created new scheduled ticker").Int("handle", handle).Str("duration", duration).Stringer("pos", thread.CallFrame(1).Pos).Send()
|
||||||
|
|
||||||
|
// Запускаем функцию немедленно при первой регистрации
|
||||||
|
go func() {
|
||||||
|
log.Info("Running plugin function immediately on startup").Str("plugin", thread.Name).Str("function", fn.Name()).Send()
|
||||||
|
_, err := starlark.Call(thread, fn, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("Error while executing initial plugin function").Str("plugin", thread.Name).Str("function", fn.Name()).Err(err).Send()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for range t.C {
|
for range t.C {
|
||||||
log.Debug("Calling scheduled function").Str("name", fn.Name()).Stringer("pos", fn.Position()).Send()
|
log.Debug("Calling scheduled function").Str("name", fn.Name()).Stringer("pos", fn.Position()).Send()
|
||||||
|
@@ -87,11 +87,34 @@ func updaterPull(cfg *config.Config) *starlark.Builtin {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Исправляем права доступа после git pull
|
||||||
|
err = fixRepoPermissions(repoDir)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("Failed to fix repository permissions after pull").Str("repo", repoName).Err(err).Send()
|
||||||
|
}
|
||||||
|
|
||||||
_ = repoConfig // Избегаем неиспользованной переменной
|
_ = repoConfig // Избегаем неиспользованной переменной
|
||||||
return starlark.None, nil
|
return starlark.None, nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fixRepoPermissions рекурсивно устанавливает права 775 для директорий и 664 для файлов
|
||||||
|
func fixRepoPermissions(path string) error {
|
||||||
|
return filepath.Walk(path, func(filePath string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.IsDir() {
|
||||||
|
// Устанавливаем права 2775 для директорий (setgid)
|
||||||
|
return os.Chmod(filePath, 0o2775)
|
||||||
|
} else {
|
||||||
|
// Устанавливаем права 664 для файлов
|
||||||
|
return os.Chmod(filePath, 0o664)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func updaterPushChanges(cfg *config.Config) *starlark.Builtin {
|
func updaterPushChanges(cfg *config.Config) *starlark.Builtin {
|
||||||
return starlark.NewBuiltin("updater.push_changes", func(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
return starlark.NewBuiltin("updater.push_changes", func(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
var repoName, msg string
|
var repoName, msg string
|
||||||
|
@@ -23,6 +23,7 @@ type Config struct {
|
|||||||
Repositories map[string]GitRepo `toml:"repositories"`
|
Repositories map[string]GitRepo `toml:"repositories"`
|
||||||
Webhook Webhook `toml:"webhook" envPrefix:"WEBHOOK_"`
|
Webhook Webhook `toml:"webhook" envPrefix:"WEBHOOK_"`
|
||||||
Logging Logging `toml:"logging" envPrefix:"LOGGING_"`
|
Logging Logging `toml:"logging" envPrefix:"LOGGING_"`
|
||||||
|
GitHub GitHub `toml:"github" envPrefix:"GITHUB_"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GitRepo struct {
|
type GitRepo struct {
|
||||||
@@ -50,3 +51,7 @@ type Logging struct {
|
|||||||
MaxSize int64 `toml:"max_size" env:"MAX_SIZE"`
|
MaxSize int64 `toml:"max_size" env:"MAX_SIZE"`
|
||||||
EnableFile bool `toml:"enable_file" env:"ENABLE_FILE"`
|
EnableFile bool `toml:"enable_file" env:"ENABLE_FILE"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GitHub struct {
|
||||||
|
Token string `toml:"token" env:"TOKEN"`
|
||||||
|
}
|
||||||
|
26
main.go
26
main.go
@@ -21,7 +21,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -244,7 +243,7 @@ func main() {
|
|||||||
log.Fatal("Error creating repository directory").Str("repo", repoName).Err(err).Send()
|
log.Fatal("Error creating repository directory").Str("repo", repoName).Err(err).Send()
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := git.PlainClone(repoDir, false, &git.CloneOptions{
|
repo, err := git.PlainClone(repoDir, false, &git.CloneOptions{
|
||||||
URL: repoConfig.RepoURL,
|
URL: repoConfig.RepoURL,
|
||||||
Progress: os.Stderr,
|
Progress: os.Stderr,
|
||||||
})
|
})
|
||||||
@@ -252,6 +251,16 @@ func main() {
|
|||||||
log.Fatal("Error cloning repository").Str("repo", repoName).Err(err).Send()
|
log.Fatal("Error cloning repository").Str("repo", repoName).Err(err).Send()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Настраиваем Git для корректной работы с правами доступа
|
||||||
|
gitConfig, err := repo.Config()
|
||||||
|
if err == nil {
|
||||||
|
gitConfig.Raw.Section("core").SetOption("sharedRepository", "group")
|
||||||
|
err = repo.SetConfig(gitConfig)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("Failed to set Git sharedRepository config").Str("repo", repoName).Err(err).Send()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Исправляем права доступа после клонирования
|
// Исправляем права доступа после клонирования
|
||||||
if err := fixRepoPermissions(repoDir); err != nil {
|
if err := fixRepoPermissions(repoDir); err != nil {
|
||||||
log.Error("Error fixing repository permissions").Str("repo", repoName).Err(err).Send()
|
log.Error("Error fixing repository permissions").Str("repo", repoName).Err(err).Send()
|
||||||
@@ -262,6 +271,19 @@ func main() {
|
|||||||
log.Fatal("Cannot stat repository directory").Str("repo", repoName).Err(err).Send()
|
log.Fatal("Cannot stat repository directory").Str("repo", repoName).Err(err).Send()
|
||||||
} else {
|
} else {
|
||||||
log.Info("Repository already exists").Str("name", repoName).Send()
|
log.Info("Repository already exists").Str("name", repoName).Send()
|
||||||
|
|
||||||
|
// Настраиваем Git конфигурацию для существующих репозиториев
|
||||||
|
repo, err := git.PlainOpen(repoDir)
|
||||||
|
if err == nil {
|
||||||
|
gitConfig, err := repo.Config()
|
||||||
|
if err == nil {
|
||||||
|
gitConfig.Raw.Section("core").SetOption("sharedRepository", "group")
|
||||||
|
err = repo.SetConfig(gitConfig)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("Failed to set Git sharedRepository config").Str("repo", repoName).Err(err).Send()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -25,6 +25,7 @@ CONFIG_DIR="/etc/alr-updater"
|
|||||||
DATA_DIR="/var/lib/alr-updater"
|
DATA_DIR="/var/lib/alr-updater"
|
||||||
CACHE_DIR="/var/cache/alr-updater"
|
CACHE_DIR="/var/cache/alr-updater"
|
||||||
PLUGIN_DIR="${CONFIG_DIR}/plugins"
|
PLUGIN_DIR="${CONFIG_DIR}/plugins"
|
||||||
|
LOG_FILE="/var/log/alr-updater.log"
|
||||||
|
|
||||||
# Создание пользователя и добавление в группу wheel
|
# Создание пользователя и добавление в группу wheel
|
||||||
echo -e "${YELLOW}Creating user and adding to wheel group...${NC}"
|
echo -e "${YELLOW}Creating user and adding to wheel group...${NC}"
|
||||||
@@ -44,6 +45,12 @@ mkdir -p ${DATA_DIR}
|
|||||||
mkdir -p ${CACHE_DIR}
|
mkdir -p ${CACHE_DIR}
|
||||||
mkdir -p ${PLUGIN_DIR}
|
mkdir -p ${PLUGIN_DIR}
|
||||||
|
|
||||||
|
# Создание файла лога
|
||||||
|
echo -e "${YELLOW}Creating log file...${NC}"
|
||||||
|
touch ${LOG_FILE}
|
||||||
|
chown ${SERVICE_USER}:${SERVICE_GROUP} ${LOG_FILE}
|
||||||
|
chmod 664 ${LOG_FILE}
|
||||||
|
|
||||||
# Установка прав доступа с setgid битом
|
# Установка прав доступа с setgid битом
|
||||||
echo -e "${YELLOW}Setting permissions with setgid...${NC}"
|
echo -e "${YELLOW}Setting permissions with setgid...${NC}"
|
||||||
chown -R root:${SERVICE_GROUP} ${DATA_DIR}
|
chown -R root:${SERVICE_GROUP} ${DATA_DIR}
|
||||||
@@ -99,7 +106,7 @@ NoNewPrivileges=true
|
|||||||
PrivateTmp=true
|
PrivateTmp=true
|
||||||
ProtectSystem=strict
|
ProtectSystem=strict
|
||||||
ProtectHome=true
|
ProtectHome=true
|
||||||
ReadWritePaths=${DATA_DIR} ${CACHE_DIR}
|
ReadWritePaths=${DATA_DIR} ${CACHE_DIR} ${LOG_FILE}
|
||||||
ReadOnlyPaths=${CONFIG_DIR}
|
ReadOnlyPaths=${CONFIG_DIR}
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
|
Reference in New Issue
Block a user