Skip to content

Commit 52cfa74

Browse files
committed
Add GET /quadlets/{name}/file
Fixes: https://issues.redhat.com/browse/RUN-3716 Signed-off-by: Nicola Sella <[email protected]>
1 parent 7958d91 commit 52cfa74

File tree

5 files changed

+107
-3
lines changed

5 files changed

+107
-3
lines changed

pkg/api/handlers/libpod/quadlets.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,25 @@ func ListQuadlets(w http.ResponseWriter, r *http.Request) {
3535

3636
utils.WriteResponse(w, http.StatusOK, quadlets)
3737
}
38+
39+
func GetQuadlet(w http.ResponseWriter, r *http.Request) {
40+
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
41+
name := utils.GetName(r)
42+
43+
containerEngine := abi.ContainerEngine{Libpod: runtime}
44+
45+
// Use QuadletPrint to get the raw file contents
46+
quadletContents, err := containerEngine.QuadletPrint(r.Context(), name)
47+
if err != nil {
48+
utils.Error(w, http.StatusNotFound, fmt.Errorf("no such quadlet: %s: %w", name, err))
49+
return
50+
}
51+
52+
// Set content type to text/plain and write the raw file contents
53+
w.Header().Set("Content-Type", "text/plain")
54+
w.WriteHeader(http.StatusOK)
55+
if _, err := w.Write([]byte(quadletContents)); err != nil {
56+
utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to write quadlet contents: %w", err))
57+
return
58+
}
59+
}

pkg/api/handlers/swagger/errors.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ type podNotFound struct {
7979
Body errorhandling.ErrorModel
8080
}
8181

82+
// No such quadlet
83+
// swagger:response
84+
type quadletNotFound struct {
85+
// in:body
86+
Body errorhandling.ErrorModel
87+
}
88+
8289
// No such manifest
8390
// swagger:response
8491
type manifestNotFound struct {

pkg/api/handlers/swagger/responses.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,3 +527,10 @@ type quadletListResponse struct {
527527
// in:body
528528
Body []entities.ListQuadlet
529529
}
530+
531+
// Quadlet file
532+
// swagger:response
533+
type quadletFileResponse struct {
534+
// in:body
535+
Body string
536+
}

pkg/api/server/register_quadlets.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,27 @@ func (s *APIServer) registerQuadletHandlers(r *mux.Router) error {
3232
// 500:
3333
// $ref: "#/responses/internalError"
3434
r.HandleFunc(VersionedPath("/libpod/quadlets/json"), s.APIHandler(libpod.ListQuadlets)).Methods(http.MethodGet)
35+
// swagger:operation GET /libpod/quadlets/{name}/file libpod QuadletFileLibpod
36+
// ---
37+
// tags:
38+
// - quadlets
39+
// summary: Get quadlet file
40+
// description: Get the contents of a Quadlet, displaying the file including all comments
41+
// produces:
42+
// - text/plain
43+
// parameters:
44+
// - in: path
45+
// name: name
46+
// type: string
47+
// required: true
48+
// description: the name of the quadlet with extension (e.g., "myapp.container")
49+
// responses:
50+
// 200:
51+
// $ref: "#/responses/quadletFileResponse"
52+
// 404:
53+
// $ref: "#/responses/quadletNotFound"
54+
// 500:
55+
// $ref: "#/responses/internalError"
56+
r.HandleFunc(VersionedPath("/libpod/quadlets/{name}/file"), s.APIHandler(libpod.GetQuadlet)).Methods(http.MethodGet)
3557
return nil
3658
}

test/apiv2/36-quadlets.at

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,56 @@
66
# NOTE: Once podman-remote quadlet support is added we can enable the podman quadlet tests in
77
# test/system/253-podman-quadlet.bats which should cover it in more detail then.
88

9-
## list volume
9+
## Test list endpoint
1010
t GET libpod/quadlets/json 200
1111

12-
# Example with filter applied (uncomment once needed)
13-
# t GET libpod/quadlets/json?filters='{"name":["name.*"]}' 200
12+
# Test 404 for non-existent quadlet
13+
t GET libpod/quadlets/nonexistent.container 404
14+
15+
# Install a quadlet with a unique name
16+
quadlet_name=quadlet-test-$(cat /proc/sys/kernel/random/uuid)
17+
18+
quadlet_container_name="$quadlet_name.container"
19+
quadlet_build_name="$quadlet_name.build"
20+
21+
quadlet_container_file_name="$HOME/.config/containers/systemd/$quadlet_container_name"
22+
quadlet_build_file_name="$HOME/.config/containers/systemd/$quadlet_build_name"
23+
24+
quadlet_container_file_content=$(cat << EOF
25+
[Container]
26+
Image=$IMAGE
27+
EOF
28+
)
29+
30+
quadlet_build_file_content=$(cat << EOF
31+
[Build]
32+
ImageTag=localhost/$quadlet_name
33+
EOF
34+
)
35+
36+
echo "$quadlet_container_file_content" > $quadlet_container_file_name
37+
echo "$quadlet_build_file_content" > $quadlet_build_file_name
38+
39+
filter_param=$(printf '{"name":["%s"]}' "$quadlet_name")
40+
t GET "libpod/quadlets/json?filters=$filter_param" 200 \
41+
length=2 \
42+
.[0].Name="$quadlet_build_name" \
43+
.[1].Name="$quadlet_container_name"
44+
45+
filter_param=$(printf '{"name":["%s"]}' "$quadlet_container_name")
46+
t GET "libpod/quadlets/json?filters=$filter_param" 200 \
47+
length=1 \
48+
.[0].Name="$quadlet_container_name"
49+
50+
t GET "libpod/quadlets/$quadlet_name/file" 404
51+
52+
t GET "libpod/quadlets/$quadlet_container_name/file" 200
53+
is "$output" "$quadlet_container_file_content"
54+
55+
t GET "libpod/quadlets/$quadlet_build_name/file" 200
56+
is "$output" "$quadlet_build_file_content"
57+
58+
rm $quadlet_container_file_name
59+
rm $quadlet_build_file_name
1460

1561
# vim: filetype=sh

0 commit comments

Comments
 (0)