mirror of
https://github.com/hauler-dev/hauler.git
synced 2026-08-27 14:07:17 +00:00
Merge pull request #140 from amartin120/retry-logic
Retry logic / Auth Flag Fix / Sync Cleanup
This commit is contained in:
@@ -98,7 +98,8 @@ func storeImage(ctx context.Context, s *store.Layout, i v1alpha1.Image) error {
|
||||
}
|
||||
|
||||
err = cosign.SaveImage(ctx, s, r.Name())
|
||||
//desc, err := s.AddOCI(ctx, img, r.Name())
|
||||
// sync with local index
|
||||
s.CopyAll(ctx, s.OCI, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -55,6 +55,13 @@ func CopyCmd(ctx context.Context, o *CopyOpts, s *store.Layout, targetRef string
|
||||
Insecure: o.Insecure,
|
||||
PlainHTTP: o.PlainHTTP,
|
||||
}
|
||||
|
||||
if ropts.Username != "" {
|
||||
err := cosign.RegistryLogin(ctx, s, components[1], ropts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err := cosign.LoadImage(ctx, s, components[1], ropts)
|
||||
if err != nil {
|
||||
|
||||
@@ -42,12 +42,6 @@ func (o *SyncOpts) AddFlags(cmd *cobra.Command) {
|
||||
func SyncCmd(ctx context.Context, o *SyncOpts, s *store.Layout) error {
|
||||
l := log.FromContext(ctx)
|
||||
|
||||
// Start from an empty store (contents are cached elsewhere)
|
||||
l.Debugf("flushing content store")
|
||||
if err := s.Flush(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// if passed products, check for a remote manifest to retrieve and use.
|
||||
for _, product := range o.Products {
|
||||
l.Infof("processing content file for product: '%s'", product)
|
||||
|
||||
+96
-50
@@ -12,6 +12,7 @@ import (
|
||||
"context"
|
||||
"strings"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"oras.land/oras-go/pkg/content"
|
||||
@@ -24,77 +25,122 @@ import (
|
||||
"github.com/rancherfederal/hauler/pkg/apis/hauler.cattle.io/v1alpha1"
|
||||
)
|
||||
|
||||
const maxRetries = 3
|
||||
const retryDelay = time.Second * 5
|
||||
|
||||
// VerifyFileSignature verifies the digital signature of a file using Sigstore/Cosign.
|
||||
func VerifySignature(ctx context.Context, s *store.Layout, keyPath string, ref string) error {
|
||||
operation := func() error {
|
||||
cosignBinaryPath, err := ensureCosignBinary(ctx, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ensure that the cosign binary is installed or download it if needed
|
||||
cosignBinaryPath, err := ensureCosignBinary(ctx, s)
|
||||
if err != nil {
|
||||
return err
|
||||
cmd := exec.Command(cosignBinaryPath, "verify", "--insecure-ignore-tlog", "--key", keyPath, ref)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error verifying signature: %v, output: %s", err, output)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Command to verify the signature using Cosign.
|
||||
cmd := exec.Command(cosignBinaryPath, "verify", "--insecure-ignore-tlog", "--key", keyPath, ref)
|
||||
|
||||
// Run the command and capture its output.
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error verifying signature: %v, output: %s", err, output)
|
||||
}
|
||||
|
||||
return nil
|
||||
return RetryOperation(ctx, operation)
|
||||
}
|
||||
|
||||
// SaveImage saves image and any signatures/attestations to the store.
|
||||
func SaveImage(ctx context.Context, s *store.Layout, ref string) error {
|
||||
operation := func() error {
|
||||
cosignBinaryPath, err := ensureCosignBinary(ctx, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ensure that the cosign binary is installed or download it if needed
|
||||
cosignBinaryPath, err := ensureCosignBinary(ctx, s)
|
||||
if err != nil {
|
||||
return err
|
||||
cmd := exec.Command(cosignBinaryPath, "save", ref, "--dir", s.Root)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error adding image to store: %v, output: %s", err, output)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Command to save/download an image using Cosign.
|
||||
cmd := exec.Command(cosignBinaryPath, "save", ref, "--dir", s.Root)
|
||||
|
||||
// Run the command and capture its output.
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error adding image to store: %v, output: %s", err, output)
|
||||
}
|
||||
|
||||
return nil
|
||||
return RetryOperation(ctx, operation)
|
||||
}
|
||||
|
||||
// LoadImage loads store to a remote registry.
|
||||
func LoadImage(ctx context.Context, s *store.Layout, registry string, ropts content.RegistryOptions) error {
|
||||
operation := func() error {
|
||||
cosignBinaryPath, err := ensureCosignBinary(ctx, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//Ensure that the cosign binary is installed or download it if needed
|
||||
cosignBinaryPath, err := ensureCosignBinary(ctx, s)
|
||||
if err != nil {
|
||||
return err
|
||||
cmd := exec.Command(cosignBinaryPath, "load", "--registry", registry, "--dir", s.Root)
|
||||
|
||||
// Conditionally add extra registry flags.
|
||||
if ropts.Insecure {
|
||||
cmd.Args = append(cmd.Args, "--allow-insecure-registry=true")
|
||||
}
|
||||
if ropts.PlainHTTP {
|
||||
cmd.Args = append(cmd.Args, "--allow-http-registry=true")
|
||||
}
|
||||
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error copying store: %v, output: %s", err, output)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Command to upload index to a remote registry using Cosign.
|
||||
cmd := exec.Command(cosignBinaryPath, "load", "--registry", registry, "--dir", s.Root)
|
||||
|
||||
// Conditionally add extra registry flags.
|
||||
if ropts.Insecure {
|
||||
cmd.Args = append(cmd.Args, "--allow-insecure-registry=true")
|
||||
}
|
||||
if ropts.PlainHTTP {
|
||||
cmd.Args = append(cmd.Args, "--allow-http-registry=true")
|
||||
}
|
||||
|
||||
// Run the command and capture its output.
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error adding image to store: %v, output: %s", err, output)
|
||||
}
|
||||
|
||||
return nil
|
||||
return RetryOperation(ctx, operation)
|
||||
}
|
||||
|
||||
// RegistryLogin - performs cosign login
|
||||
func RegistryLogin(ctx context.Context, s *store.Layout, registry string, ropts content.RegistryOptions) error {
|
||||
operation := func() error {
|
||||
cosignBinaryPath, err := ensureCosignBinary(ctx, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := exec.Command(cosignBinaryPath, "login", registry, "-u", ropts.Username, "-p", ropts.Password)
|
||||
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error logging into registry: %v, output: %s", err, output)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return RetryOperation(ctx, operation)
|
||||
}
|
||||
|
||||
func RetryOperation(ctx context.Context, operation func() error) error {
|
||||
l := log.FromContext(ctx)
|
||||
for attempt := 1; attempt <= maxRetries; attempt++ {
|
||||
err := operation()
|
||||
if err == nil {
|
||||
// If the operation succeeds, return nil (no error).
|
||||
return nil
|
||||
}
|
||||
|
||||
// Log the error for the current attempt.
|
||||
l.Errorf("Error (attempt %d/%d): %v", attempt, maxRetries, err)
|
||||
|
||||
// If this is not the last attempt, wait before retrying.
|
||||
if attempt < maxRetries {
|
||||
time.Sleep(retryDelay)
|
||||
}
|
||||
}
|
||||
|
||||
// If all attempts fail, return an error.
|
||||
return fmt.Errorf("operation failed after %d attempts", maxRetries)
|
||||
}
|
||||
|
||||
|
||||
// ensureCosignBinary checks if the cosign binary exists in the specified directory and installs it if not.
|
||||
func ensureCosignBinary(ctx context.Context, s *store.Layout) (string, error) {
|
||||
l := log.FromContext(ctx)
|
||||
|
||||
Reference in New Issue
Block a user