mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-05-01 13:35:46 +00:00
70 lines
1.8 KiB
Go
70 lines
1.8 KiB
Go
package holdclient
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
|
|
"atcr.io/pkg/atproto"
|
|
)
|
|
|
|
// OCIHistoryEntry represents a single entry in the OCI config history.
|
|
type OCIHistoryEntry struct {
|
|
Created string `json:"created"`
|
|
CreatedBy string `json:"created_by"`
|
|
EmptyLayer bool `json:"empty_layer"`
|
|
Comment string `json:"comment"`
|
|
}
|
|
|
|
// OCIConfig represents the parsed OCI image config with fields useful for display.
|
|
type OCIConfig struct {
|
|
History []OCIHistoryEntry `json:"history"`
|
|
}
|
|
|
|
// FetchImageConfig fetches the OCI image config record from the hold's
|
|
// getImageConfig XRPC endpoint. holdURL should be a resolved HTTP(S) URL.
|
|
// Returns the parsed OCI config with history entries.
|
|
func FetchImageConfig(ctx context.Context, holdURL, manifestDigest string) (*OCIConfig, error) {
|
|
reqURL := fmt.Sprintf("%s%s?digest=%s",
|
|
strings.TrimSuffix(holdURL, "/"),
|
|
atproto.HoldGetImageConfig,
|
|
url.QueryEscape(manifestDigest),
|
|
)
|
|
|
|
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
|
defer cancel()
|
|
|
|
req, err := http.NewRequestWithContext(ctx, "GET", reqURL, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("build request: %w", err)
|
|
}
|
|
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("fetch image config: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return nil, fmt.Errorf("hold returned status %d for %s", resp.StatusCode, reqURL)
|
|
}
|
|
|
|
var record struct {
|
|
ConfigJSON string `json:"configJson"`
|
|
}
|
|
if err := json.NewDecoder(resp.Body).Decode(&record); err != nil {
|
|
return nil, fmt.Errorf("parse image config response: %w", err)
|
|
}
|
|
|
|
var config OCIConfig
|
|
if err := json.Unmarshal([]byte(record.ConfigJSON), &config); err != nil {
|
|
return nil, fmt.Errorf("parse OCI config JSON: %w", err)
|
|
}
|
|
|
|
return &config, nil
|
|
}
|