first with full handle over rpm
Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
This commit is contained in:
parent
7948368573
commit
274ea454dd
50 changed files with 4309 additions and 0 deletions
9
cmd/clonepack/main.go
Normal file
9
cmd/clonepack/main.go
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
package main
|
||||
|
||||
import "os"
|
||||
|
||||
func main() {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
498
cmd/clonepack/repo.go
Normal file
498
cmd/clonepack/repo.go
Normal file
|
|
@ -0,0 +1,498 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/syonad/clonepack/client"
|
||||
)
|
||||
|
||||
var repoCloneCmd = &cobra.Command{
|
||||
Use: "clone <id>",
|
||||
Short: "Clone an RPM repository",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
id, err := strconv.ParseInt(args[0], 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid id: %s", args[0])
|
||||
}
|
||||
c := client.New(apiURL)
|
||||
|
||||
resp, err := c.StartClone(cmd.Context(), id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("start clone: %w", err)
|
||||
}
|
||||
fmt.Printf("Clone job started: job_id=%d\n", resp.JobID)
|
||||
|
||||
ticker := time.NewTicker(2 * time.Second)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-cmd.Context().Done():
|
||||
return cmd.Context().Err()
|
||||
case <-ticker.C:
|
||||
status, err := c.GetCloneStatus(cmd.Context(), id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get status: %w", err)
|
||||
}
|
||||
fmt.Printf(" status: %s\n", status.Status)
|
||||
switch status.Status {
|
||||
case "completed":
|
||||
fmt.Println("Clone completed successfully.")
|
||||
return nil
|
||||
case "failed":
|
||||
errMsg := "(unknown error)"
|
||||
if status.Error != nil {
|
||||
errMsg = *status.Error
|
||||
}
|
||||
return fmt.Errorf("clone failed: %s", errMsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
var repoCmd = &cobra.Command{
|
||||
Use: "repo",
|
||||
Short: "Manage repositories",
|
||||
}
|
||||
|
||||
var (
|
||||
repoName string
|
||||
repoType string
|
||||
repoSourceURL string
|
||||
)
|
||||
|
||||
var repoCreateCmd = &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Create a new repository",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
c := client.New(apiURL)
|
||||
repo, err := c.CreateRepo(cmd.Context(), client.CreateRepoInput{
|
||||
Name: repoName,
|
||||
Type: repoType,
|
||||
SourceURL: repoSourceURL,
|
||||
SyncMode: repoSyncMode,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printRepos([]client.Repo{*repo})
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var repoListCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List all repositories",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
c := client.New(apiURL)
|
||||
repos, err := c.ListRepos(cmd.Context())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(repos) == 0 {
|
||||
fmt.Println("No repositories found.")
|
||||
return nil
|
||||
}
|
||||
printRepos(repos)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var repoGetCmd = &cobra.Command{
|
||||
Use: "get <id>",
|
||||
Short: "Get a repository by ID",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
id, err := strconv.ParseInt(args[0], 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid id: %s", args[0])
|
||||
}
|
||||
c := client.New(apiURL)
|
||||
repo, err := c.GetRepo(cmd.Context(), id)
|
||||
if errors.Is(err, client.ErrNotFound) {
|
||||
return fmt.Errorf("repo %d not found", id)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printRepos([]client.Repo{*repo})
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var repoDeleteCmd = &cobra.Command{
|
||||
Use: "delete <id>",
|
||||
Short: "Delete a repository by ID",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
id, err := strconv.ParseInt(args[0], 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid id: %s", args[0])
|
||||
}
|
||||
c := client.New(apiURL)
|
||||
if err := c.DeleteRepo(cmd.Context(), id); errors.Is(err, client.ErrNotFound) {
|
||||
return fmt.Errorf("repo %d not found", id)
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Deleted repo %d\n", id)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func printRepos(repos []client.Repo) {
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||
fmt.Fprintln(w, "ID\tNAME\tTYPE\tSOURCE URL\tFROZEN\tSYNC MODE\tCREATED AT")
|
||||
for _, r := range repos {
|
||||
fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%v\t%s\t%s\n",
|
||||
r.ID, r.Name, r.Type, r.SourceURL, r.Frozen, r.SyncMode,
|
||||
r.CreatedAt.Format(time.RFC3339),
|
||||
)
|
||||
}
|
||||
w.Flush()
|
||||
}
|
||||
|
||||
var repoSyncCmd = &cobra.Command{
|
||||
Use: "sync <id>",
|
||||
Short: "Trigger a sync scan for a repository",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
id, _ := strconv.ParseInt(args[0], 10, 64)
|
||||
c := client.New(apiURL)
|
||||
if err := c.TriggerSync(cmd.Context(), id); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("Scan started. Use 'sync-list' to check pending packages.")
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var repoSyncListCmd = &cobra.Command{
|
||||
Use: "sync-list <id>",
|
||||
Short: "List packages pending approval for a repository",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
id, _ := strconv.ParseInt(args[0], 10, 64)
|
||||
c := client.New(apiURL)
|
||||
pkgs, err := c.ListPending(cmd.Context(), id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(pkgs) == 0 {
|
||||
fmt.Println("No packages pending approval.")
|
||||
return nil
|
||||
}
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||
fmt.Fprintln(w, "ID\tNAME\tVERSION\tARCH\tSIZE")
|
||||
for _, p := range pkgs {
|
||||
fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%d\n", p.ID, p.Name, p.Version, p.Arch, p.Size)
|
||||
}
|
||||
w.Flush()
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var syncApproveAll bool
|
||||
|
||||
var repoSyncApproveCmd = &cobra.Command{
|
||||
Use: "sync-approve <repo_id> [pkg_id...]",
|
||||
Short: "Approve pending packages for download",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
repoID, _ := strconv.ParseInt(args[0], 10, 64)
|
||||
c := client.New(apiURL)
|
||||
|
||||
var ids []int64
|
||||
if syncApproveAll {
|
||||
pkgs, err := c.ListPending(cmd.Context(), repoID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("list pending: %w", err)
|
||||
}
|
||||
if len(pkgs) == 0 {
|
||||
fmt.Println("No packages pending approval.")
|
||||
return nil
|
||||
}
|
||||
for _, p := range pkgs {
|
||||
ids = append(ids, p.ID)
|
||||
}
|
||||
} else {
|
||||
if len(args) < 2 {
|
||||
return fmt.Errorf("provide package IDs or use --all")
|
||||
}
|
||||
for _, a := range args[1:] {
|
||||
id, err := strconv.ParseInt(a, 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid pkg id: %s", a)
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
}
|
||||
|
||||
if err := c.ApprovePending(cmd.Context(), repoID, ids); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Approval started for %d package(s). Downloads running in background.\n", len(ids))
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var repoSyncRejectCmd = &cobra.Command{
|
||||
Use: "sync-reject <repo_id> <pkg_id>...",
|
||||
Short: "Reject pending packages",
|
||||
Args: cobra.MinimumNArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
repoID, _ := strconv.ParseInt(args[0], 10, 64)
|
||||
var ids []int64
|
||||
for _, a := range args[1:] {
|
||||
id, _ := strconv.ParseInt(a, 10, 64)
|
||||
ids = append(ids, id)
|
||||
}
|
||||
c := client.New(apiURL)
|
||||
if err := c.RejectPending(cmd.Context(), repoID, ids); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Rejected %d package(s)\n", len(ids))
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var repoSyncBlockCmd = &cobra.Command{
|
||||
Use: "sync-block <repo_id> <pkg_id>...",
|
||||
Short: "Bloquer définitivement des paquets (par ID pending)",
|
||||
Args: cobra.MinimumNArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
repoID, _ := strconv.ParseInt(args[0], 10, 64)
|
||||
var ids []int64
|
||||
for _, a := range args[1:] {
|
||||
id, err := strconv.ParseInt(a, 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid id: %s", a)
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
c := client.New(apiURL)
|
||||
if err := c.BlockPackages(cmd.Context(), repoID, ids); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("%d paquet(s) bloqué(s) définitivement.\n", len(ids))
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var repoSyncUnblockCmd = &cobra.Command{
|
||||
Use: "sync-unblock <repo_id> <blocked_id>...",
|
||||
Short: "Débloquer des paquets (par ID blocked)",
|
||||
Args: cobra.MinimumNArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
repoID, _ := strconv.ParseInt(args[0], 10, 64)
|
||||
var ids []int64
|
||||
for _, a := range args[1:] {
|
||||
id, _ := strconv.ParseInt(a, 10, 64)
|
||||
ids = append(ids, id)
|
||||
}
|
||||
c := client.New(apiURL)
|
||||
if err := c.UnblockPackages(cmd.Context(), repoID, ids); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("%d paquet(s) débloqué(s).\n", len(ids))
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var repoSyncBlockListCmd = &cobra.Command{
|
||||
Use: "sync-blocklist <repo_id>",
|
||||
Short: "Lister les paquets bloqués définitivement",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
repoID, _ := strconv.ParseInt(args[0], 10, 64)
|
||||
c := client.New(apiURL)
|
||||
pkgs, err := c.ListBlocked(cmd.Context(), repoID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(pkgs) == 0 {
|
||||
fmt.Println("Aucun paquet bloqué.")
|
||||
return nil
|
||||
}
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||
fmt.Fprintln(w, "ID\tNOM\tLOCATION\tBLOQUÉ LE")
|
||||
for _, p := range pkgs {
|
||||
fmt.Fprintf(w, "%d\t%s\t%s\t%s\n", p.ID, p.Name, p.Location, p.CreatedAt.Format(time.RFC3339))
|
||||
}
|
||||
w.Flush()
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var repoSnapshotCmd = &cobra.Command{
|
||||
Use: "snapshot",
|
||||
Short: "Manage repository snapshots",
|
||||
}
|
||||
|
||||
var repoSnapshotCreateCmd = &cobra.Command{
|
||||
Use: "create <repo_id>",
|
||||
Short: "Create a snapshot of a repository",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
repoID, _ := strconv.ParseInt(args[0], 10, 64)
|
||||
c := client.New(apiURL)
|
||||
snap, err := c.CreateSnapshot(cmd.Context(), repoID, snapshotLabel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printSnapshots([]client.Snapshot{*snap})
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var repoSnapshotListCmd = &cobra.Command{
|
||||
Use: "list <repo_id>",
|
||||
Short: "List snapshots of a repository",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
repoID, _ := strconv.ParseInt(args[0], 10, 64)
|
||||
c := client.New(apiURL)
|
||||
snaps, err := c.ListSnapshots(cmd.Context(), repoID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(snaps) == 0 {
|
||||
fmt.Println("No snapshots found.")
|
||||
return nil
|
||||
}
|
||||
printSnapshots(snaps)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var repoSnapshotShowCmd = &cobra.Command{
|
||||
Use: "show <repo_id> <snap_id>",
|
||||
Short: "Show snapshot details",
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
repoID, _ := strconv.ParseInt(args[0], 10, 64)
|
||||
snapID, _ := strconv.ParseInt(args[1], 10, 64)
|
||||
c := client.New(apiURL)
|
||||
detail, err := c.GetSnapshot(cmd.Context(), repoID, snapID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printSnapshots([]client.Snapshot{detail.Snapshot})
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||
fmt.Fprintln(w, "NAME\tVERSION\tARCH\tSIZE")
|
||||
for _, p := range detail.Packages {
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%d\n", p.Name, p.Version, p.Arch, p.Size)
|
||||
}
|
||||
w.Flush()
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var repoSnapshotDeleteCmd = &cobra.Command{
|
||||
Use: "delete <repo_id> <snap_id>",
|
||||
Short: "Delete a snapshot",
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
repoID, _ := strconv.ParseInt(args[0], 10, 64)
|
||||
snapID, _ := strconv.ParseInt(args[1], 10, 64)
|
||||
c := client.New(apiURL)
|
||||
if err := c.DeleteSnapshot(cmd.Context(), repoID, snapID); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Deleted snapshot %d\n", snapID)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var repoSnapshotDiffCmd = &cobra.Command{
|
||||
Use: "diff <repo_id> <from_snap_id> <to_snap_id>",
|
||||
Short: "Diff two snapshots",
|
||||
Args: cobra.ExactArgs(3),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
repoID, _ := strconv.ParseInt(args[0], 10, 64)
|
||||
fromID, _ := strconv.ParseInt(args[1], 10, 64)
|
||||
toID, _ := strconv.ParseInt(args[2], 10, 64)
|
||||
c := client.New(apiURL)
|
||||
diff, err := c.DiffSnapshots(cmd.Context(), repoID, fromID, toID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("From: [%d] %s\nTo: [%d] %s\nUnchanged: %d\n",
|
||||
diff.From.ID, diff.From.Label, diff.To.ID, diff.To.Label, diff.Unchanged)
|
||||
if len(diff.Added) > 0 {
|
||||
fmt.Printf("\nAdded (%d):\n", len(diff.Added))
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||
fmt.Fprintln(w, " NAME\tVERSION\tARCH")
|
||||
for _, p := range diff.Added {
|
||||
fmt.Fprintf(w, " %s\t%s\t%s\n", p.Name, p.Version, p.Arch)
|
||||
}
|
||||
w.Flush()
|
||||
}
|
||||
if len(diff.Removed) > 0 {
|
||||
fmt.Printf("\nRemoved (%d):\n", len(diff.Removed))
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||
fmt.Fprintln(w, " NAME\tVERSION\tARCH")
|
||||
for _, p := range diff.Removed {
|
||||
fmt.Fprintf(w, " %s\t%s\t%s\n", p.Name, p.Version, p.Arch)
|
||||
}
|
||||
w.Flush()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var repoSnapshotRollbackCmd = &cobra.Command{
|
||||
Use: "rollback <repo_id> <snap_id>",
|
||||
Short: "Rollback repository to a snapshot",
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
repoID, _ := strconv.ParseInt(args[0], 10, 64)
|
||||
snapID, _ := strconv.ParseInt(args[1], 10, 64)
|
||||
c := client.New(apiURL)
|
||||
if err := c.RollbackSnapshot(cmd.Context(), repoID, snapID); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("Rollback completed.")
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func printSnapshots(snaps []client.Snapshot) {
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||
fmt.Fprintln(w, "ID\tREPO ID\tLABEL\tCREATED AT")
|
||||
for _, s := range snaps {
|
||||
fmt.Fprintf(w, "%d\t%d\t%s\t%s\n", s.ID, s.RepoID, s.Label, s.CreatedAt.Format(time.RFC3339))
|
||||
}
|
||||
w.Flush()
|
||||
}
|
||||
|
||||
var snapshotLabel string
|
||||
var repoSyncMode string
|
||||
|
||||
func init() {
|
||||
repoCreateCmd.Flags().StringVar(&repoName, "name", "", "Repository name (required)")
|
||||
repoCreateCmd.Flags().StringVar(&repoType, "type", "", "Type: apt|rpm|docker|binary (required)")
|
||||
repoCreateCmd.Flags().StringVar(&repoSourceURL, "source-url", "", "Upstream source URL (required)")
|
||||
repoCreateCmd.Flags().StringVar(&repoSyncMode, "sync-mode", "auto", "Sync mode: auto|manual")
|
||||
repoCreateCmd.MarkFlagRequired("name")
|
||||
repoCreateCmd.MarkFlagRequired("type")
|
||||
repoCreateCmd.MarkFlagRequired("source-url")
|
||||
|
||||
repoSyncApproveCmd.Flags().BoolVar(&syncApproveAll, "all", false, "Approuver tous les paquets en attente")
|
||||
|
||||
repoSnapshotCreateCmd.Flags().StringVar(&snapshotLabel, "label", "", "Snapshot label")
|
||||
repoSnapshotCmd.AddCommand(repoSnapshotCreateCmd, repoSnapshotListCmd, repoSnapshotShowCmd,
|
||||
repoSnapshotDeleteCmd, repoSnapshotDiffCmd, repoSnapshotRollbackCmd)
|
||||
|
||||
repoCmd.AddCommand(repoCreateCmd, repoListCmd, repoGetCmd, repoDeleteCmd, repoCloneCmd,
|
||||
repoSyncCmd, repoSyncListCmd, repoSyncApproveCmd, repoSyncRejectCmd,
|
||||
repoSyncBlockCmd, repoSyncUnblockCmd, repoSyncBlockListCmd,
|
||||
repoSnapshotCmd)
|
||||
}
|
||||
20
cmd/clonepack/root.go
Normal file
20
cmd/clonepack/root.go
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package main
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
var (
|
||||
cfgFile string
|
||||
apiURL string
|
||||
)
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "clonepack",
|
||||
Short: "ClonePack artifact mirror manager",
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file path")
|
||||
rootCmd.PersistentFlags().StringVar(&apiURL, "api-url", "http://localhost:8080", "ClonePack server URL")
|
||||
rootCmd.AddCommand(serveCmd)
|
||||
rootCmd.AddCommand(repoCmd)
|
||||
}
|
||||
60
cmd/clonepack/serve.go
Normal file
60
cmd/clonepack/serve.go
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/syonad/clonepack/config"
|
||||
"github.com/syonad/clonepack/internal/api"
|
||||
"github.com/syonad/clonepack/internal/core"
|
||||
"github.com/syonad/clonepack/internal/store"
|
||||
)
|
||||
|
||||
var serveCmd = &cobra.Command{
|
||||
Use: "serve",
|
||||
Short: "Start the ClonePack HTTP server",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
cfg, err := config.Load(cfgFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("load config: %w", err)
|
||||
}
|
||||
|
||||
db, err := store.Open(cfg.DB)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open store: %w", err)
|
||||
}
|
||||
|
||||
repoStore := store.NewRepoStore(db)
|
||||
jobStore := store.NewCloneJobStore(db)
|
||||
pendingStore := store.NewPendingPackageStore(db)
|
||||
blockedStore := store.NewBlockedPackageStore(db)
|
||||
snapshotStore := store.NewSnapshotStore(db)
|
||||
|
||||
repoSvc := core.NewRepoService(repoStore, cfg.DataDir)
|
||||
cloneSvc := core.NewCloneService(repoStore, jobStore, cfg.DataDir)
|
||||
snapshotSvc := core.NewSnapshotService(snapshotStore, repoStore, cfg.DataDir)
|
||||
syncSvc := core.NewSyncService(repoStore, pendingStore, blockedStore, cloneSvc, snapshotSvc, cfg.DataDir)
|
||||
|
||||
repoH := api.NewRepoHandler(repoSvc)
|
||||
cloneH := api.NewCloneHandler(cloneSvc)
|
||||
syncH := api.NewSyncHandler(syncSvc)
|
||||
snapshotH := api.NewSnapshotHandler(snapshotSvc)
|
||||
proxyH := api.NewProxyHandler(repoSvc, cfg.DataDir)
|
||||
router := api.NewRouter(repoH, cloneH, syncH, snapshotH, proxyH)
|
||||
|
||||
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||
defer cancel()
|
||||
|
||||
syncSvc.StartScheduler(ctx, cfg.Sync.IntervalDuration())
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port)
|
||||
log.Printf("ClonePack listening on %s", addr)
|
||||
return http.ListenAndServe(addr, router)
|
||||
},
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue