Documentation
¶
Overview ¶
Package apk provides CloudEvents types for APK package registry operations.
Overview ¶
This package defines event types and data structures for tracking APK package push and pull operations in the Chainguard registry. These events are emitted as CloudEvents and can be consumed by event processing systems for auditing, analytics, and monitoring purposes.
Features ¶
- PushEvent: Captures metadata when APK packages are pushed to the registry
- PullEvent: Captures metadata when APK packages are pulled from the registry
- Location tracking: Records approximate geographic location of clients
- Proxy support: Tracks pulls through virtualapk.cgr.dev proxy with UIDP and hash
- Error reporting: Includes error details for failed push operations
Event Types ¶
The package defines two CloudEvents event types:
- dev.chainguard.apk.push.v1: Emitted when an APK is pushed
- dev.chainguard.apk.pull.v1: Emitted when an APK is pulled
Usage ¶
Events are typically consumed from a CloudEvents source and unmarshaled into the appropriate event type:
import (
"encoding/json"
cloudevents "github.com/cloudevents/sdk-go/v2"
"chainguard.dev/sdk/events/apk"
)
func handleEvent(event cloudevents.Event) error {
switch event.Type() {
case apk.PushedEventType:
var push apk.PushEvent
if err := event.DataAs(&push); err != nil {
return err
}
// Process push event
log.Printf("Package pushed: %s/%s-%s", push.Architecture, push.Package, push.Version)
case apk.PulledEventType:
var pull apk.PullEvent
if err := event.DataAs(&pull); err != nil {
return err
}
// Process pull event
log.Printf("Package pulled: %s", pull.APKPath())
}
return nil
}
Integration Patterns ¶
Events can be consumed from various sources:
- Cloud Pub/Sub subscriptions
- HTTP CloudEvents endpoints
- Event streaming platforms
Example integration with Cloud Pub/Sub:
import (
"cloud.google.com/go/pubsub"
cloudevents "github.com/cloudevents/sdk-go/v2"
"chainguard.dev/sdk/events/apk"
)
func processPubSubMessage(msg *pubsub.Message) error {
event := cloudevents.NewEvent()
if err := json.Unmarshal(msg.Data, &event); err != nil {
return err
}
if event.Type() == apk.PushedEventType {
var push apk.PushEvent
if err := event.DataAs(&push); err != nil {
return err
}
// Handle push event
}
return nil
}
Path Construction ¶
Both PushEvent and PullEvent provide convenience methods for constructing APK file paths:
- APKPath(): Returns the full path including repository ID
- APKBasePath(): Returns the base path without repository ID
These methods follow the standard APK repository layout: {architecture}/{package}-{version}.apk
Example ¶
Example demonstrates basic usage of PushEvent and its methods.
package main
import (
"fmt"
"time"
"chainguard.dev/sdk/civil"
"chainguard.dev/sdk/events/apk"
)
func main() {
push := apk.PushEvent{
Repository: "example-repo",
RepoID: "abc123def456",
Package: "nginx",
Origin: "nginx",
Version: "1.25.3-r0",
Architecture: "x86_64",
Checksum: "Q1abc123def456",
When: civil.DateTimeOf(time.Date(2024, 1, 15, 10, 30, 0, 0, time.UTC)),
Location: "SeattleWAUS",
RemoteAddress: "203.0.113.42",
UserAgent: "apk-tools/2.14.0",
}
fmt.Println("Package:", push.Package)
fmt.Println("Version:", push.Version)
fmt.Println("Base Path:", push.APKBasePath())
fmt.Println("Full Path:", push.APKPath())
}
Output: Package: nginx Version: 1.25.3-r0 Base Path: x86_64/nginx-1.25.3-r0.apk Full Path: abc123def456/x86_64/nginx-1.25.3-r0.apk
Index ¶
Examples ¶
Constants ¶
const ( // PushedEventType is the cloudevents event type for APK pushes PushedEventType = "dev.chainguard.apk.push.v1" // PulledEventType is the cloudevents event type for APK pulls PulledEventType = "dev.chainguard.apk.pull.v1" // WithdrawnEventType is the cloudevents event type for APK withdrawals WithdrawnEventType = "dev.chainguard.apk.withdraw.v1" )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type PullEvent ¶ added in v0.1.39
type PullEvent struct {
// Repository identifies the repository being pulled
Repository string `json:"repository"`
// RepoID identifies the UIDP of the APK repository (group) being pulled
RepoID string `json:"repo_id"`
// Package holds the name of the package being pushed.
Package string `json:"package"`
// Origin holds the name of the origin package being pushed. For
// subpackages, this is the name of the parent package, for main packages,
// this is the same as Package.
Origin string `json:"origin_package"`
// Version holds the version of the package being pushed.
Version string `json:"version"`
// Architecture holds the architecture of the package being pushed.
Architecture string `json:"architecture"`
// Checksum holds the checksum of the package's control section as
// it would appear in an APKINDEX entry for the package.
Checksum string `json:"checksum"`
// When holds when the pull occurred.
When civil.DateTime `json:"when"`
// Location holds the detected approximate location of the client who pulled.
// For example, "ColumbusOHUS" or "Minato City13JP".
Location string `json:"location"`
// RemoteAddress holds the address of the client who pulled.
RemoteAddress string `json:"remote_address"`
// UserAgent holds the user-agent of the client who pulled.
UserAgent string `json:"user_agent"`
// ProxyUIDP is the UIDP of the customer associated with the apkproxy pull, if any.
// This is only set if the pull was proxied through virtualapk.cgr.dev/<uidp>(/<hash>?)/original/<arch>/<pkg>.apk.
ProxyUIDP string `json:"proxy_uidp,omitempty"`
// ProxyHash is the hash of the image associated with the apkproxy pull, if any.
// This is only set if the pull was proxied through virtualapk.cgr.dev/<uidp>/<hash>/original/<arch>/<pkg>.apk.
ProxyHash string `json:"proxy_hash,omitempty"`
}
PullEvent describes an APK being pulled from the registry.
Example ¶
ExamplePullEvent demonstrates creating and using a PullEvent.
package main
import (
"fmt"
"chainguard.dev/sdk/events/apk"
)
func main() {
event := apk.PullEvent{
Repository: "chainguard",
RepoID: "repo-uidp-456",
Package: "git",
Origin: "git",
Version: "2.43.0-r0",
Architecture: "x86_64",
Checksum: "Q1checksum",
Location: "TokyoJP",
RemoteAddress: "203.0.113.100",
UserAgent: "apk-tools/2.14.0",
}
fmt.Println(event.APKPath())
}
Output: repo-uidp-456/x86_64/git-2.43.0-r0.apk
Example (Proxy) ¶
ExamplePullEvent_proxy demonstrates a PullEvent with proxy information.
package main
import (
"fmt"
"chainguard.dev/sdk/events/apk"
)
func main() {
event := apk.PullEvent{
Package: "alpine-base",
Version: "3.19.0-r0",
Architecture: "x86_64",
ProxyUIDP: "customer-uidp-789",
ProxyHash: "sha256:abc123",
}
if event.ProxyUIDP != "" {
fmt.Printf("Proxied pull for customer: %s\n", event.ProxyUIDP)
if event.ProxyHash != "" {
fmt.Printf("Image hash: %s\n", event.ProxyHash)
}
}
}
Output: Proxied pull for customer: customer-uidp-789 Image hash: sha256:abc123
func (PullEvent) APKBasePath ¶ added in v0.1.39
APKBasePath is a convenience method for constructing the base path to the APK.
Example ¶
ExamplePullEvent_aPKBasePath demonstrates the APKBasePath method for PullEvent.
package main
import (
"fmt"
"chainguard.dev/sdk/events/apk"
)
func main() {
event := apk.PullEvent{
Package: "python3",
Version: "3.12.1-r0",
Architecture: "aarch64",
}
fmt.Println(event.APKBasePath())
}
Output: aarch64/python3-3.12.1-r0.apk
func (PullEvent) APKPath ¶ added in v0.1.39
APKPath is a convenience method for constructing the full path to the APK.
Example ¶
ExamplePullEvent_aPKPath demonstrates the APKPath method for PullEvent.
package main
import (
"fmt"
"chainguard.dev/sdk/events/apk"
)
func main() {
event := apk.PullEvent{
RepoID: "customer-repo",
Package: "nodejs",
Version: "20.10.0-r0",
Architecture: "x86_64",
}
fmt.Println(event.APKPath())
}
Output: customer-repo/x86_64/nodejs-20.10.0-r0.apk
type PushEvent ¶
type PushEvent struct {
// Repository identifies the repository being pushed
Repository string `json:"repository"`
// RepoID identifies the UIDP of the APK repository (group) being pushed
RepoID string `json:"repo_id"`
// Package holds the name of the package being pushed.
Package string `json:"package"`
// Origin holds the name of the origin package being pushed. For
// subpackages, this is the name of the parent package, for main packages,
// this is the same as Package.
Origin string `json:"origin_package"`
// Version holds the version of the package being pushed.
Version string `json:"version"`
// Architecture holds the architecture of the package being pushed.
Architecture string `json:"architecture"`
// Checksum holds the checksum of the package's control section as
// it would appear in an APKINDEX entry for the package.
Checksum string `json:"checksum"`
// When holds when the push occurred.
When civil.DateTime `json:"when"`
// Location holds the detected approximate location of the client who pushed.
// For example, "ColumbusOHUS" or "Minato City13JP".
Location string `json:"location"`
// RemoteAddress holds the address of the client who pushed.
RemoteAddress string `json:"remote_address"`
// UserAgent holds the user-agent of the client who pushed.
UserAgent string `json:"user_agent"`
Error *Error `json:"error,omitempty"`
}
PushEvent describes an APK being pushed to the registry.
Example ¶
ExamplePushEvent demonstrates creating and using a PushEvent.
package main
import (
"fmt"
"chainguard.dev/sdk/events/apk"
)
func main() {
event := apk.PushEvent{
Repository: "chainguard",
RepoID: "repo-uidp-123",
Package: "curl",
Origin: "curl",
Version: "8.5.0-r0",
Architecture: "aarch64",
Checksum: "Q1checksum",
Location: "LondonGB",
RemoteAddress: "198.51.100.10",
UserAgent: "apk-tools/2.14.0",
}
fmt.Println(event.APKPath())
}
Output: repo-uidp-123/aarch64/curl-8.5.0-r0.apk
Example (Error) ¶
ExamplePushEvent_error demonstrates a PushEvent with an error.
package main
import (
"fmt"
"chainguard.dev/sdk/events/apk"
)
func main() {
event := apk.PushEvent{
Package: "invalid-pkg",
Error: &apk.Error{
Status: 403,
Code: "FORBIDDEN",
Message: "insufficient permissions",
},
}
if event.Error != nil {
fmt.Printf("Push failed: %s (status %d)\n", event.Error.Message, event.Error.Status)
}
}
Output: Push failed: insufficient permissions (status 403)
func (PushEvent) APKBasePath ¶ added in v0.1.26
APKBasePath is a convenience method for constructing the base path to the APK.
Example ¶
ExamplePushEvent_aPKBasePath demonstrates the APKBasePath method.
package main
import (
"fmt"
"chainguard.dev/sdk/events/apk"
)
func main() {
event := apk.PushEvent{
Package: "busybox",
Version: "1.36.1-r0",
Architecture: "x86_64",
}
fmt.Println(event.APKBasePath())
}
Output: x86_64/busybox-1.36.1-r0.apk
func (PushEvent) APKPath ¶ added in v0.1.25
APKPath is a convenience method for constructing the full path to the APK.
Example ¶
ExamplePushEvent_aPKPath demonstrates the APKPath method.
package main
import (
"fmt"
"chainguard.dev/sdk/events/apk"
)
func main() {
event := apk.PushEvent{
RepoID: "my-repo-id",
Package: "openssl",
Version: "3.1.4-r0",
Architecture: "armv7",
}
fmt.Println(event.APKPath())
}
Output: my-repo-id/armv7/openssl-3.1.4-r0.apk
type WithdrawEvent ¶ added in v0.1.56
type WithdrawEvent struct {
// Repository identifies the repository the withdrawal was made from.
Repository string `json:"repository"`
// RepoID identifies the UIDP of the APK repository being withdrawn from.
RepoID string `json:"repo_id"`
// Architecture holds the architecture of the withdrawn packages.
Architecture string `json:"architecture"`
// WithdrawnCount holds the number of packages successfully withdrawn.
WithdrawnCount int32 `json:"withdrawn_count"`
// When holds when the withdrawal occurred.
When civil.DateTime `json:"when"`
}
WithdrawEvent describes an APK withdrawal from a source repository.