init
This commit is contained in:
commit
13897488df
4 changed files with 212 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
bin/*
|
25
Makefile
Normal file
25
Makefile
Normal file
|
@ -0,0 +1,25 @@
|
|||
BINARY_NAME=aides-uploader
|
||||
|
||||
SRC_DIR=.
|
||||
BUILD_DIR=./bin
|
||||
|
||||
GO=go
|
||||
|
||||
build:
|
||||
mkdir -p $(BUILD_DIR)
|
||||
$(GO) build -o $(BUILD_DIR)/$(BINARY_NAME) $(SRC_DIR)
|
||||
|
||||
run: build
|
||||
$(BUILD_DIR)/$(BINARY_NAME)
|
||||
|
||||
test:
|
||||
$(GO) test ./...
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR)
|
||||
|
||||
deps:
|
||||
$(GO) mod tidy
|
||||
$(GO) mod download
|
||||
|
||||
all: build
|
3
go.mod
Normal file
3
go.mod
Normal file
|
@ -0,0 +1,3 @@
|
|||
module code.alt-gnome.ru/aides-infra/aides-uploader
|
||||
|
||||
go 1.23.2
|
183
main.go
Normal file
183
main.go
Normal file
|
@ -0,0 +1,183 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Configuration struct {
|
||||
ServerURL string
|
||||
Repo string
|
||||
TaskID string
|
||||
Token string
|
||||
FilePatterns []string
|
||||
Files []string
|
||||
}
|
||||
|
||||
func parseFlags() Configuration {
|
||||
var cfg Configuration
|
||||
|
||||
flag.StringVar(&cfg.ServerURL, "url", "http://localhost:9999", "Базовый URL сервера загрузки")
|
||||
flag.StringVar(&cfg.Repo, "repo", "", "Название репозитория (обязательно)")
|
||||
flag.StringVar(&cfg.TaskID, "task", "", "ID задачи (обязательно)")
|
||||
flag.StringVar(&cfg.Token, "token", "", "Токен авторизации (обязательно)")
|
||||
files := flag.String("files", "", "Список путей к файлам или паттернов (разделены запятой) для загрузки (обязательно)")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
missing := false
|
||||
if cfg.Repo == "" {
|
||||
fmt.Println("Ошибка: -repo является обязательным")
|
||||
missing = true
|
||||
}
|
||||
if cfg.TaskID == "" {
|
||||
fmt.Println("Ошибка: -task является обязательным")
|
||||
missing = true
|
||||
}
|
||||
if cfg.Token == "" {
|
||||
fmt.Println("Ошибка: -token является обязательным")
|
||||
missing = true
|
||||
}
|
||||
if *files == "" {
|
||||
fmt.Println("Ошибка: -files является обязательным")
|
||||
missing = true
|
||||
}
|
||||
if missing {
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
cfg.FilePatterns = splitAndTrim(*files, ",")
|
||||
|
||||
var allFiles []string
|
||||
for _, pattern := range cfg.FilePatterns {
|
||||
matches, err := filepath.Glob(pattern)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Неверный паттерн glob '%s': %v\n", pattern, err)
|
||||
continue
|
||||
}
|
||||
if len(matches) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "Предупреждение: Паттерн '%s' не совпадает ни с одним файлом\n", pattern)
|
||||
continue
|
||||
}
|
||||
allFiles = append(allFiles, matches...)
|
||||
}
|
||||
|
||||
cfg.Files = unique(allFiles)
|
||||
|
||||
if len(cfg.Files) == 0 {
|
||||
fmt.Println("Ошибка: Не найдено файлов для загрузки после обработки паттернов")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
func splitAndTrim(s, sep string) []string {
|
||||
parts := strings.Split(s, sep)
|
||||
var trimmed []string
|
||||
for _, part := range parts {
|
||||
part = strings.TrimSpace(part)
|
||||
if part != "" {
|
||||
trimmed = append(trimmed, part)
|
||||
}
|
||||
}
|
||||
return trimmed
|
||||
}
|
||||
|
||||
func unique(input []string) []string {
|
||||
seen := make(map[string]struct{})
|
||||
var result []string
|
||||
for _, item := range input {
|
||||
if _, exists := seen[item]; !exists {
|
||||
seen[item] = struct{}{}
|
||||
result = append(result, item)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func createMultipartRequest(url string, files []string, token string) (*http.Request, error) {
|
||||
var buf bytes.Buffer
|
||||
writer := multipart.NewWriter(&buf)
|
||||
|
||||
for _, filePath := range files {
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("не удалось открыть файл %s: %w", filePath, err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
part, err := writer.CreateFormFile("files", filepath.Base(filePath))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("не удалось создать поле формы для файла %s: %w", filePath, err)
|
||||
}
|
||||
|
||||
_, err = io.Copy(part, file)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("не удалось скопировать содержимое файла %s: %w", filePath, err)
|
||||
}
|
||||
}
|
||||
|
||||
err := writer.Close()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("не удалось закрыть multipart писатель: %w", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", url, &buf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("не удалось создать HTTP-запрос: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func uploadFiles(cfg Configuration) error {
|
||||
uploadURL := fmt.Sprintf("%s/upload/%s/task/%s", strings.TrimRight(cfg.ServerURL, "/"), cfg.Repo, cfg.TaskID)
|
||||
|
||||
req, err := createMultipartRequest(uploadURL, cfg.Files, cfg.Token)
|
||||
if err != nil {
|
||||
return fmt.Errorf("не удалось создать multipart-запрос: %w", err)
|
||||
}
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("не удалось выполнить HTTP-запрос: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("не удалось прочитать тело ответа: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("загрузка не удалась с кодом %d: %s", resp.StatusCode, string(respBody))
|
||||
}
|
||||
|
||||
fmt.Println("Загрузка успешна:")
|
||||
fmt.Println(string(respBody))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
cfg := parseFlags()
|
||||
|
||||
err := uploadFiles(cfg)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Ошибка: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue