Skip to content

Commit a0f0a95

Browse files
feat: Implement auto update support for podman-remote
Signed-off-by: Stefan Nienhuis <[email protected]>
1 parent e47ae67 commit a0f0a95

File tree

13 files changed

+362
-12
lines changed

13 files changed

+362
-12
lines changed

cmd/podman/auto-update.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ var (
3131
or similar units that create new containers in order to run the updated images.
3232
Please refer to the podman-auto-update(1) man page for details.`
3333
autoUpdateCommand = &cobra.Command{
34-
Annotations: map[string]string{registry.EngineMode: registry.ABIMode},
3534
Use: "auto-update [options]",
3635
Short: "Auto update containers according to their auto-update policy",
3736
Long: autoUpdateDescription,

hack/swagger-check

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,11 @@ sub operation_name {
343343
$main = 'image';
344344
$action = $1;
345345
}
346+
# Top-level autoupdate endpoint
347+
elsif ($main eq 'autoupdate') {
348+
$main = 'autoupdate';
349+
$action = '';
350+
}
346351
# Top-level system endpoints
347352
elsif ($main =~ /^(auth|event|info|version)$/) {
348353
$main = 'system';
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//go:build !remote
2+
3+
package libpod
4+
5+
import (
6+
"fmt"
7+
"net/http"
8+
9+
"github.com/containers/podman/v5/libpod"
10+
"github.com/containers/podman/v5/pkg/api/handlers"
11+
"github.com/containers/podman/v5/pkg/api/handlers/utils"
12+
api "github.com/containers/podman/v5/pkg/api/types"
13+
"github.com/containers/podman/v5/pkg/auth"
14+
"github.com/containers/podman/v5/pkg/domain/entities"
15+
"github.com/containers/podman/v5/pkg/domain/infra/abi"
16+
"github.com/containers/podman/v5/pkg/errorhandling"
17+
"github.com/gorilla/schema"
18+
"go.podman.io/image/v5/types"
19+
)
20+
21+
func AutoUpdate(w http.ResponseWriter, r *http.Request) {
22+
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
23+
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
24+
25+
query := struct {
26+
DryRun bool `schema:"dryRun"`
27+
Rollback bool `schema:"rollback"`
28+
TLSVerify types.OptionalBool `schema:"tlsVerify"`
29+
}{}
30+
31+
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
32+
utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err))
33+
return
34+
}
35+
36+
_, authfile, err := auth.GetCredentials(r)
37+
if err != nil {
38+
utils.Error(w, http.StatusBadRequest, err)
39+
return
40+
}
41+
defer auth.RemoveAuthfile(authfile)
42+
43+
containerEngine := abi.ContainerEngine{Libpod: runtime}
44+
45+
options := entities.AutoUpdateOptions{
46+
Authfile: authfile,
47+
DryRun: query.DryRun,
48+
Rollback: query.Rollback,
49+
InsecureSkipTLSVerify: types.OptionalBoolUndefined,
50+
}
51+
52+
// If TLS verification is explicitly specified (True or False) in the query,
53+
// set the InsecureSkipTLSVerify option accordingly.
54+
// If TLSVerify was not set in the query, OptionalBoolUndefined is used and
55+
// handled later based off the target registry configuration.
56+
switch query.TLSVerify {
57+
case types.OptionalBoolTrue:
58+
options.InsecureSkipTLSVerify = types.NewOptionalBool(false)
59+
case types.OptionalBoolFalse:
60+
options.InsecureSkipTLSVerify = types.NewOptionalBool(true)
61+
case types.OptionalBoolUndefined:
62+
// If the user doesn't define TLSVerify in the query, do nothing and pass
63+
// it to the backend code to handle.
64+
default: // Should never happen
65+
panic("Unexpected handling occurred for TLSVerify")
66+
}
67+
68+
autoUpdateReports, autoUpdateFailures := containerEngine.AutoUpdate(r.Context(), options)
69+
if autoUpdateReports == nil {
70+
if err := errorhandling.JoinErrors(autoUpdateFailures); err != nil {
71+
utils.Error(w, http.StatusInternalServerError, err)
72+
return
73+
}
74+
}
75+
76+
reports := handlers.LibpodAutoUpdateReports{Reports: autoUpdateReports, Errors: errorhandling.ErrorsToStrings(autoUpdateFailures)}
77+
78+
utils.WriteResponse(w, http.StatusOK, reports)
79+
}

pkg/api/handlers/swagger/responses.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,3 +520,10 @@ type artifactPushResponse struct {
520520
// in:body
521521
Body entities.ArtifactPushReport
522522
}
523+
524+
// Auto Update
525+
// swagger:response
526+
type autoupdateResponse struct {
527+
// in:body
528+
Body handlers.LibpodAutoUpdateReports
529+
}

pkg/api/handlers/types.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,3 +188,10 @@ type ExecStartConfig struct {
188188
type ExecRemoveConfig struct {
189189
Force bool `json:"Force"`
190190
}
191+
192+
// LibpodAutoUpdateReport is the return type for auto update via the rest api.
193+
type LibpodAutoUpdateReports struct {
194+
Reports []*entities.AutoUpdateReport
195+
// Auto update returns data and possible errors.
196+
Errors []string
197+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//go:build !remote
2+
3+
package server
4+
5+
import (
6+
"net/http"
7+
8+
"github.com/containers/podman/v5/pkg/api/handlers/libpod"
9+
"github.com/gorilla/mux"
10+
)
11+
12+
func (s *APIServer) registerAutoUpdateHandlers(r *mux.Router) error {
13+
// swagger:operation POST /libpod/autoupdate libpod AutoupdateLibpod
14+
// ---
15+
// tags:
16+
// - autoupdate
17+
// summary: Auto update
18+
// description: |
19+
// Auto update containers according to their auto-update policy.
20+
//
21+
// Auto-update policies are specified with the "io.containers.autoupdate" label.
22+
// Containers are expected to run in systemd units created with "podman-generate-systemd --new",
23+
// or similar units that create new containers in order to run the updated images.
24+
// Please refer to the podman-auto-update(1) man page for details.
25+
// parameters:
26+
// - in: query
27+
// name: authfile
28+
// type: string
29+
// description: Authfile to use when contacting registries.
30+
// - in: query
31+
// name: dryRun
32+
// type: boolean
33+
// description: Only check for but do not perform any update. If an update is pending, it will be indicated in the Updated field.
34+
// - in: query
35+
// name: rollback
36+
// type: boolean
37+
// description: If restarting the service with the new image failed, restart it another time with the previous image.
38+
// - in: query
39+
// name: tlsVerify
40+
// type: boolean
41+
// default: true
42+
// description: Require HTTPS and verify signatures when contacting registries.
43+
// produces:
44+
// - application/json
45+
// responses:
46+
// 200:
47+
// $ref: "#/responses/autoupdateResponse"
48+
// 500:
49+
// $ref: '#/responses/internalError'
50+
r.HandleFunc(VersionedPath("/libpod/autoupdate"), s.APIHandler(libpod.AutoUpdate)).Methods(http.MethodPost)
51+
return nil
52+
}

pkg/api/server/server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ func newServer(runtime *libpod.Runtime, listener net.Listener, opts entities.Ser
133133
server.registerAuthHandlers,
134134
server.registerArtifactHandlers,
135135
server.registerArchiveHandlers,
136+
server.registerAutoUpdateHandlers,
136137
server.registerContainersHandlers,
137138
server.registerDistributionHandlers,
138139
server.registerEventsHandlers,

pkg/api/tags.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
tags:
22
- name: artifacts
33
description: Actions related to artifacts
4+
- name: autoupdate
5+
description: Actions related to auto update
46
- name: containers
57
description: Actions related to containers
68
- name: exec
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package autoupdate
2+
3+
import (
4+
"context"
5+
"net/http"
6+
"strconv"
7+
8+
"github.com/containers/podman/v5/pkg/api/handlers"
9+
"github.com/containers/podman/v5/pkg/auth"
10+
"github.com/containers/podman/v5/pkg/bindings"
11+
"github.com/containers/podman/v5/pkg/domain/entities"
12+
"github.com/containers/podman/v5/pkg/errorhandling"
13+
imageTypes "go.podman.io/image/v5/types"
14+
)
15+
16+
func AutoUpdate(ctx context.Context, options *AutoUpdateOptions) ([]*entities.AutoUpdateReport, []error) {
17+
conn, err := bindings.GetClient(ctx)
18+
if err != nil {
19+
return nil, []error{err}
20+
}
21+
if options == nil {
22+
options = new(AutoUpdateOptions)
23+
}
24+
25+
params, err := options.ToParams()
26+
if err != nil {
27+
return nil, []error{err}
28+
}
29+
// InsecureSkipTLSVerify is special. We need to delete the param added by
30+
// ToParams() and change the key and flip the bool
31+
if options.InsecureSkipTLSVerify != nil {
32+
params.Del("SkipTLSVerify")
33+
params.Set("tlsVerify", strconv.FormatBool(!options.GetInsecureSkipTLSVerify()))
34+
}
35+
36+
header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, "", "")
37+
if err != nil {
38+
return nil, []error{err}
39+
}
40+
41+
response, err := conn.DoRequest(ctx, nil, http.MethodPost, "/autoupdate", params, header)
42+
if err != nil {
43+
return nil, []error{err}
44+
}
45+
defer response.Body.Close()
46+
47+
var reports handlers.LibpodAutoUpdateReports
48+
49+
if err := response.Process(&reports); err != nil {
50+
return nil, []error{err}
51+
}
52+
53+
return reports.Reports, errorhandling.StringsToErrors(reports.Errors)
54+
}

pkg/bindings/auto-update/types.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package autoupdate
2+
3+
// AutoUpdateOptions are the options for running auto-update
4+
//
5+
//go:generate go run ../generator/generator.go AutoUpdateOptions
6+
type AutoUpdateOptions struct {
7+
// Authfile to use when contacting registries.
8+
Authfile *string
9+
// Only check for but do not perform any update. If an update is
10+
// pending, it will be indicated in the Updated field of
11+
// AutoUpdateReport.
12+
DryRun *bool
13+
// If restarting the service with the new image failed, restart it
14+
// another time with the previous image.
15+
Rollback *bool
16+
// Allow contacting registries over HTTP, or HTTPS with failed TLS
17+
// verification. Note that this does not affect other TLS connections.
18+
InsecureSkipTLSVerify *bool
19+
}

0 commit comments

Comments
 (0)