Skip to content

Commit 9c98257

Browse files
authored
Merge pull request #1434 from stgraber/image
Allow setting aliases during raw image upload
2 parents 278a42e + d8b64ff commit 9c98257

File tree

5 files changed

+56
-6
lines changed

5 files changed

+56
-6
lines changed

client/incus_images.go

+10
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,16 @@ func (r *ProtocolIncus) CreateImage(image api.ImagesPost, args *ImageCreateArgs)
556556
req.Header.Set("X-Incus-profiles", imgProfiles.Encode())
557557
}
558558

559+
if len(image.Aliases) > 0 {
560+
imgProfiles := url.Values{}
561+
562+
for _, v := range image.Aliases {
563+
imgProfiles.Add("alias", v.Name)
564+
}
565+
566+
req.Header.Set("X-Incus-aliases", imgProfiles.Encode())
567+
}
568+
559569
// Set the user agent
560570
if image.Source != nil && image.Source.Fingerprint != "" && image.Source.Secret != "" && image.Source.Mode == "push" {
561571
// Set fingerprint

cmd/incusd/images.go

+34-6
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,7 @@ func getImgPostInfo(ctx context.Context, s *state.State, r *http.Request, buildd
596596
info.Public = util.IsTrue(r.Header.Get("X-Incus-public"))
597597
propHeaders := r.Header[http.CanonicalHeaderKey("X-Incus-properties")]
598598
profilesHeaders := r.Header.Get("X-Incus-profiles")
599+
aliasesHeaders := r.Header.Get("X-Incus-aliases")
599600
ctype, ctypeParams, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
600601
if err != nil {
601602
ctype = "application/octet-stream"
@@ -781,6 +782,19 @@ func getImgPostInfo(ctx context.Context, s *state.State, r *http.Request, buildd
781782
}
782783
}
783784

785+
if len(aliasesHeaders) > 0 {
786+
info.Aliases = []api.ImageAlias{}
787+
aliasNames, _ := url.ParseQuery(aliasesHeaders)
788+
789+
for _, aliasName := range aliasNames["alias"] {
790+
alias := api.ImageAlias{
791+
Name: aliasName,
792+
}
793+
794+
info.Aliases = append(info.Aliases, alias)
795+
}
796+
}
797+
784798
var profileIds []int64
785799
if len(profilesHeaders) > 0 {
786800
p, _ := url.ParseQuery(profilesHeaders)
@@ -806,7 +820,6 @@ func getImgPostInfo(ctx context.Context, s *state.State, r *http.Request, buildd
806820
}
807821

808822
var exists bool
809-
810823
err = s.DB.Cluster.Transaction(ctx, func(ctx context.Context, tx *db.ClusterTx) error {
811824
// Check if the image already exists
812825
exists, err = tx.ImageExists(ctx, project, info.Fingerprint)
@@ -945,6 +958,13 @@ func imageCreateInPool(s *state.State, info *api.Image, storagePool string) erro
945958
// schema:
946959
// type: string
947960
// - in: header
961+
// name: X-Incus-aliases
962+
// description: List of aliases to assign
963+
// schema:
964+
// type: array
965+
// items:
966+
// type: string
967+
// - in: header
948968
// name: X-Incus-properties
949969
// description: Descriptive properties
950970
// schema:
@@ -996,7 +1016,6 @@ func imagesPost(d *Daemon, r *http.Request) response.Response {
9961016
fingerprint := r.Header.Get("X-Incus-fingerprint")
9971017

9981018
var imageMetadata map[string]any
999-
10001019
if !trusted && (secret == "" || fingerprint == "") {
10011020
return response.Forbidden(nil)
10021021
} else {
@@ -1172,9 +1191,18 @@ func imagesPost(d *Daemon, r *http.Request) response.Response {
11721191
}
11731192

11741193
// Apply any provided alias
1175-
aliases, ok := imageMetadata["aliases"]
1176-
if ok {
1177-
req.Aliases = aliases.([]api.ImageAlias)
1194+
if len(req.Aliases) == 0 {
1195+
aliases, ok := imageMetadata["aliases"]
1196+
if ok {
1197+
// Used to get aliases from push mode image copy operation.
1198+
aliases, ok := aliases.([]api.ImageAlias)
1199+
if ok {
1200+
req.Aliases = aliases
1201+
}
1202+
} else if len(info.Aliases) > 0 {
1203+
// Used to get aliases from HTTP headers on raw image imports.
1204+
req.Aliases = info.Aliases
1205+
}
11781206
}
11791207

11801208
err = s.DB.Cluster.Transaction(context.TODO(), func(ctx context.Context, tx *db.ClusterTx) error {
@@ -1199,7 +1227,7 @@ func imagesPost(d *Daemon, r *http.Request) response.Response {
11991227
}
12001228

12011229
// Add the image alias to the authorizer.
1202-
err = s.Authorizer.AddImageAlias(r.Context(), projectName, alias.Name)
1230+
err = s.Authorizer.AddImageAlias(ctx, projectName, alias.Name)
12031231
if err != nil {
12041232
logger.Error("Failed to add image alias to authorizer", logger.Ctx{"name": alias.Name, "project": projectName, "error": err})
12051233
}

doc/api-extensions.md

+4
Original file line numberDiff line numberDiff line change
@@ -2664,3 +2664,7 @@ This adds support for virtual-machines live-migration between storage pools.
26642664
## `instance_console_screenshot`
26652665

26662666
This adds support to take screenshots of the current VGA console of a VM.
2667+
2668+
## `image_import_alias`
2669+
2670+
Adds a new `X-Incus-aliases` HTTP header to set aliases while uploading an image.

doc/rest-api.yaml

+7
Original file line numberDiff line numberDiff line change
@@ -7834,6 +7834,13 @@ paths:
78347834
name: X-Incus-fingerprint
78357835
schema:
78367836
type: string
7837+
- description: List of aliases to assign
7838+
in: header
7839+
name: X-Incus-aliases
7840+
schema:
7841+
items:
7842+
type: string
7843+
type: array
78377844
- description: Descriptive properties
78387845
in: header
78397846
name: X-Incus-properties

internal/version/api.go

+1
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,7 @@ var APIExtensions = []string{
453453
"storage_initial_owner",
454454
"storage_live_migration",
455455
"instance_console_screenshot",
456+
"image_import_alias",
456457
}
457458

458459
// APIExtensionsCount returns the number of available API extensions.

0 commit comments

Comments
 (0)