From 609b52f7266dc057ec356348e54e501225715c4d Mon Sep 17 00:00:00 2001
From: Paul Holzinger <pholzing@redhat.com>
Date: Tue, 29 Mar 2022 19:00:46 +0200
Subject: Bump version to v4.1.0-dev

I think we forgot to bump the version in the main branch. It should be
v4.1.0-dev now.
Also set the min api version to 4.0.0 as on the podman 4.0 branch.

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
---
 pkg/bindings/test/manifests_test.go | 2 +-
 test/apiv2/01-basic.at              | 2 +-
 version/version.go                  | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/pkg/bindings/test/manifests_test.go b/pkg/bindings/test/manifests_test.go
index 64becda43..e6c93817d 100644
--- a/pkg/bindings/test/manifests_test.go
+++ b/pkg/bindings/test/manifests_test.go
@@ -96,7 +96,7 @@ var _ = Describe("podman manifest", func() {
 		Expect(err).To(HaveOccurred())
 
 		code, _ = bindings.CheckResponseCode(err)
-		Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+		Expect(code).To(BeNumerically("==", http.StatusBadRequest))
 	})
 
 	It("remove digest", func() {
diff --git a/test/apiv2/01-basic.at b/test/apiv2/01-basic.at
index 2747ccbd4..e4348a9a7 100644
--- a/test/apiv2/01-basic.at
+++ b/test/apiv2/01-basic.at
@@ -19,7 +19,7 @@ for i in /version version; do
     t GET  $i      200                               \
       .Components[0].Name="Podman Engine"            \
       .Components[0].Details.APIVersion~4[0-9.-]\\+  \
-      .Components[0].Details.MinAPIVersion=3.1.0     \
+      .Components[0].Details.MinAPIVersion=4.0.0     \
       .Components[0].Details.Os=linux                \
       .ApiVersion=1.40                               \
       .MinAPIVersion=1.24                            \
diff --git a/version/version.go b/version/version.go
index c6bd2c239..5b2ca0d74 100644
--- a/version/version.go
+++ b/version/version.go
@@ -27,7 +27,7 @@ const (
 // NOTE: remember to bump the version at the top
 // of the top-level README.md file when this is
 // bumped.
-var Version = semver.MustParse("4.0.0-dev")
+var Version = semver.MustParse("4.1.0-dev")
 
 // See https://docs.docker.com/engine/api/v1.40/
 // libpod compat handlers are expected to honor docker API versions
@@ -38,7 +38,7 @@ var Version = semver.MustParse("4.0.0-dev")
 var APIVersion = map[Tree]map[Level]semver.Version{
 	Libpod: {
 		CurrentAPI: Version,
-		MinimalAPI: semver.MustParse("3.1.0"),
+		MinimalAPI: semver.MustParse("4.0.0"),
 	},
 	Compat: {
 		CurrentAPI: semver.MustParse("1.40.0"),
-- 
cgit v1.2.3-54-g00ecf


From e9599fb1ae49551c51cd1c8f4cb98ef93231d842 Mon Sep 17 00:00:00 2001
From: Paul Holzinger <pholzing@redhat.com>
Date: Wed, 27 Apr 2022 12:41:15 +0200
Subject: fix manifest modify endpoint to respect tlsverify param

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
---
 pkg/api/handlers/libpod/manifests.go | 10 ++++++++++
 pkg/api/server/register_manifest.go  |  5 +++++
 2 files changed, 15 insertions(+)

diff --git a/pkg/api/handlers/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go
index 15d4b9f89..8dc7c57d5 100644
--- a/pkg/api/handlers/libpod/manifests.go
+++ b/pkg/api/handlers/libpod/manifests.go
@@ -7,6 +7,7 @@ import (
 	"io/ioutil"
 	"net/http"
 	"net/url"
+	"strconv"
 	"strings"
 
 	"github.com/containers/image/v5/docker/reference"
@@ -372,6 +373,15 @@ func ManifestModify(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
+	if tlsVerify, ok := r.URL.Query()["tlsVerify"]; ok {
+		tls, err := strconv.ParseBool(tlsVerify[len(tlsVerify)-1])
+		if err != nil {
+			utils.Error(w, http.StatusBadRequest, fmt.Errorf("tlsVerify param is not a bool: %w", err))
+			return
+		}
+		body.SkipTLSVerify = types.NewOptionalBool(!tls)
+	}
+
 	authconf, authfile, err := auth.GetCredentials(r)
 	if err != nil {
 		utils.Error(w, http.StatusBadRequest, err)
diff --git a/pkg/api/server/register_manifest.go b/pkg/api/server/register_manifest.go
index 50a49bc1e..75ff38bea 100644
--- a/pkg/api/server/register_manifest.go
+++ b/pkg/api/server/register_manifest.go
@@ -116,6 +116,11 @@ func (s *APIServer) registerManifestHandlers(r *mux.Router) error {
 	//    type: string
 	//    required: true
 	//    description: the name or ID of the manifest
+	//  - in: query
+	//    name: tlsVerify
+	//    type: boolean
+	//    default: false
+	//    description: skip TLS verification for registries
 	//  - in: body
 	//    name: options
 	//    description: options for mutating a manifest
-- 
cgit v1.2.3-54-g00ecf


From 4a4906b91f6ff59f5cbc542d31b6127b5d8f5bc8 Mon Sep 17 00:00:00 2001
From: Paul Holzinger <pholzing@redhat.com>
Date: Wed, 27 Apr 2022 12:43:16 +0200
Subject: pkg/bindings: manifest remove 3.X API support conditional

Since the minimum API version is set to 4.0.0 the endpoint will not talk
to the 3.X endpoint. Therefore this logic is broken and should just be
removed. 4.0 bindings should only talk to 4.0 server. This is already
the case for many other endpoints.

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
---
 pkg/bindings/manifests/manifests.go | 91 ++++++++-----------------------------
 1 file changed, 18 insertions(+), 73 deletions(-)

diff --git a/pkg/bindings/manifests/manifests.go b/pkg/bindings/manifests/manifests.go
index 70b3819f5..828f4922c 100644
--- a/pkg/bindings/manifests/manifests.go
+++ b/pkg/bindings/manifests/manifests.go
@@ -2,13 +2,11 @@ package manifests
 
 import (
 	"context"
-	"fmt"
 	"io/ioutil"
 	"net/http"
 	"strconv"
 	"strings"
 
-	"github.com/blang/semver"
 	"github.com/containers/image/v5/manifest"
 	imageTypes "github.com/containers/image/v5/types"
 	"github.com/containers/podman/v4/pkg/api/handlers"
@@ -17,7 +15,6 @@ import (
 	"github.com/containers/podman/v4/pkg/bindings/images"
 	"github.com/containers/podman/v4/pkg/domain/entities"
 	"github.com/containers/podman/v4/pkg/errorhandling"
-	"github.com/containers/podman/v4/version"
 	jsoniter "github.com/json-iterator/go"
 	"github.com/pkg/errors"
 )
@@ -95,65 +92,23 @@ func Add(ctx context.Context, name string, options *AddOptions) (string, error)
 		options = new(AddOptions)
 	}
 
-	if bindings.ServiceVersion(ctx).GTE(semver.MustParse("4.0.0")) {
-		optionsv4 := ModifyOptions{
-			All:           options.All,
-			Annotations:   options.Annotation,
-			Arch:          options.Arch,
-			Features:      options.Features,
-			Images:        options.Images,
-			OS:            options.OS,
-			OSFeatures:    nil,
-			OSVersion:     options.OSVersion,
-			Variant:       options.Variant,
-			Username:      options.Username,
-			Password:      options.Password,
-			Authfile:      options.Authfile,
-			SkipTLSVerify: options.SkipTLSVerify,
-		}
-		optionsv4.WithOperation("update")
-		return Modify(ctx, name, options.Images, &optionsv4)
-	}
-
-	// API Version < 4.0.0
-	conn, err := bindings.GetClient(ctx)
-	if err != nil {
-		return "", err
-	}
-	opts, err := jsoniter.MarshalToString(options)
-	if err != nil {
-		return "", err
-	}
-	reader := strings.NewReader(opts)
-
-	header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword())
-	if err != nil {
-		return "", err
-	}
-
-	params, err := options.ToParams()
-	if err != nil {
-		return "", err
-	}
-	// SkipTLSVerify is special.  We need to delete the param added by
-	// ToParams() and change the key and flip the bool
-	if options.SkipTLSVerify != nil {
-		params.Del("SkipTLSVerify")
-		params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify()))
-	}
-
-	v := version.APIVersion[version.Libpod][version.MinimalAPI]
-	header.Add("API-Version",
-		fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch))
-
-	response, err := conn.DoRequest(ctx, reader, http.MethodPost, "/manifests/%s/add", params, header, name)
-	if err != nil {
-		return "", err
-	}
-	defer response.Body.Close()
-
-	var idr handlers.IDResponse
-	return idr.ID, response.Process(&idr)
+	optionsv4 := ModifyOptions{
+		All:           options.All,
+		Annotations:   options.Annotation,
+		Arch:          options.Arch,
+		Features:      options.Features,
+		Images:        options.Images,
+		OS:            options.OS,
+		OSFeatures:    nil,
+		OSVersion:     options.OSVersion,
+		Variant:       options.Variant,
+		Username:      options.Username,
+		Password:      options.Password,
+		Authfile:      options.Authfile,
+		SkipTLSVerify: options.SkipTLSVerify,
+	}
+	optionsv4.WithOperation("update")
+	return Modify(ctx, name, options.Images, &optionsv4)
 }
 
 // Remove deletes a manifest entry from a manifest list.  Both name and the digest to be
@@ -185,9 +140,6 @@ func Push(ctx context.Context, name, destination string, options *images.PushOpt
 	if err != nil {
 		return "", err
 	}
-	v := version.APIVersion[version.Libpod][version.MinimalAPI]
-	header.Add("API-Version",
-		fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch))
 
 	params, err := options.ToParams()
 	if err != nil {
@@ -200,14 +152,7 @@ func Push(ctx context.Context, name, destination string, options *images.PushOpt
 		params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify()))
 	}
 
-	var response *bindings.APIResponse
-	if bindings.ServiceVersion(ctx).GTE(semver.MustParse("4.0.0")) {
-		response, err = conn.DoRequest(ctx, nil, http.MethodPost, "/manifests/%s/registry/%s", params, header, name, destination)
-	} else {
-		params.Set("image", name)
-		params.Set("destination", destination)
-		response, err = conn.DoRequest(ctx, nil, http.MethodPost, "/manifests/%s/push", params, header, name)
-	}
+	response, err := conn.DoRequest(ctx, nil, http.MethodPost, "/manifests/%s/registry/%s", params, header, name, destination)
 	if err != nil {
 		return "", err
 	}
-- 
cgit v1.2.3-54-g00ecf


From 3bcfd256b3253d248cf458509c05c7940f7e58cb Mon Sep 17 00:00:00 2001
From: Paul Holzinger <pholzing@redhat.com>
Date: Wed, 27 Apr 2022 14:57:25 +0200
Subject: manifest endpoints fix ordering

OK this is a pretty bad design IMO. We have to endpoints:
manifest create: `POST /{name}`
manifest push: `POST /{name}/registry/{destination}`

So basically all push requests are valid create requests.
Fortunately we can change the order in which the endpoints are matched.
If the logic matches push first it will fall back to create if the
request does not have the `/registry/{}` part.

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
---
 pkg/api/server/register_manifest.go | 152 ++++++++++++++++++------------------
 1 file changed, 76 insertions(+), 76 deletions(-)

diff --git a/pkg/api/server/register_manifest.go b/pkg/api/server/register_manifest.go
index 75ff38bea..3e3a516f4 100644
--- a/pkg/api/server/register_manifest.go
+++ b/pkg/api/server/register_manifest.go
@@ -10,6 +10,82 @@ import (
 func (s *APIServer) registerManifestHandlers(r *mux.Router) error {
 	v3 := r.PathPrefix("/v{version:[0-3][0-9A-Za-z.-]*}/libpod/manifests").Subrouter()
 	v4 := r.PathPrefix("/v{version:[4-9][0-9A-Za-z.-]*}/libpod/manifests").Subrouter()
+	// swagger:operation POST /libpod/manifests/{name}/push manifests ManifestPushV3Libpod
+	// ---
+	// summary: Push manifest to registry
+	// description: |
+	//   Push a manifest list or image index to a registry
+	//
+	//   Deprecated: As of 4.0.0 use ManifestPushLibpod instead
+	// produces:
+	// - application/json
+	// parameters:
+	//  - in: path
+	//    name: name
+	//    type: string
+	//    required: true
+	//    description: the name or ID of the manifest
+	//  - in: query
+	//    name: destination
+	//    type: string
+	//    required: true
+	//    description: the destination for the manifest
+	//  - in: query
+	//    name: all
+	//    description: push all images
+	//    type: boolean
+	// responses:
+	//   200:
+	//     schema:
+	//       $ref: "#/definitions/IDResponse"
+	//   400:
+	//     $ref: "#/responses/BadParamError"
+	//   404:
+	//     $ref: "#/responses/NoSuchManifest"
+	//   500:
+	//     $ref: "#/responses/InternalError"
+	v3.Handle("/{name}/push", s.APIHandler(libpod.ManifestPushV3)).Methods(http.MethodPost)
+	// swagger:operation POST /libpod/manifests/{name}/registry/{destination} manifests ManifestPushLibpod
+	// ---
+	// summary: Push manifest list to registry
+	// description: |
+	//   Push a manifest list or image index to the named registry
+	//
+	//   As of v4.0.0
+	// produces:
+	// - application/json
+	// parameters:
+	//  - in: path
+	//    name: name
+	//    type: string
+	//    required: true
+	//    description: the name or ID of the manifest list
+	//  - in: path
+	//    name: destination
+	//    type: string
+	//    required: true
+	//    description: the registry for the manifest list
+	//  - in: query
+	//    name: all
+	//    description: push all images
+	//    type: boolean
+	//    default: false
+	//  - in: query
+	//    name: tlsVerify
+	//    type: boolean
+	//    default: false
+	//    description: skip TLS verification for registries
+	// responses:
+	//   200:
+	//     schema:
+	//       $ref: "#/definitions/IDResponse"
+	//   400:
+	//     $ref: "#/responses/BadParamError"
+	//   404:
+	//     $ref: "#/responses/NoSuchManifest"
+	//   500:
+	//     $ref: "#/responses/InternalError"
+	v4.Handle("/{name:.*}/registry/{destination:.*}", s.APIHandler(libpod.ManifestPush)).Methods(http.MethodPost)
 	// swagger:operation POST /libpod/manifests manifests ManifestCreateLibpod
 	// ---
 	// summary: Create
@@ -226,81 +302,5 @@ func (s *APIServer) registerManifestHandlers(r *mux.Router) error {
 	//   500:
 	//     $ref: "#/responses/InternalError"
 	v4.Handle("/{name:.*}", s.APIHandler(libpod.ManifestDelete)).Methods(http.MethodDelete)
-	// swagger:operation POST /libpod/manifests/{name}/push manifests ManifestPushV3Libpod
-	// ---
-	// summary: Push manifest to registry
-	// description: |
-	//   Push a manifest list or image index to a registry
-	//
-	//   Deprecated: As of 4.0.0 use ManifestPushLibpod instead
-	// produces:
-	// - application/json
-	// parameters:
-	//  - in: path
-	//    name: name
-	//    type: string
-	//    required: true
-	//    description: the name or ID of the manifest
-	//  - in: query
-	//    name: destination
-	//    type: string
-	//    required: true
-	//    description: the destination for the manifest
-	//  - in: query
-	//    name: all
-	//    description: push all images
-	//    type: boolean
-	// responses:
-	//   200:
-	//     schema:
-	//       $ref: "#/definitions/IDResponse"
-	//   400:
-	//     $ref: "#/responses/BadParamError"
-	//   404:
-	//     $ref: "#/responses/NoSuchManifest"
-	//   500:
-	//     $ref: "#/responses/InternalError"
-	v3.Handle("/{name}/push", s.APIHandler(libpod.ManifestPushV3)).Methods(http.MethodPost)
-	// swagger:operation POST /libpod/manifests/{name}/registry/{destination} manifests ManifestPushLibpod
-	// ---
-	// summary: Push manifest list to registry
-	// description: |
-	//   Push a manifest list or image index to the named registry
-	//
-	//   As of v4.0.0
-	// produces:
-	// - application/json
-	// parameters:
-	//  - in: path
-	//    name: name
-	//    type: string
-	//    required: true
-	//    description: the name or ID of the manifest list
-	//  - in: path
-	//    name: destination
-	//    type: string
-	//    required: true
-	//    description: the registry for the manifest list
-	//  - in: query
-	//    name: all
-	//    description: push all images
-	//    type: boolean
-	//    default: false
-	//  - in: query
-	//    name: tlsVerify
-	//    type: boolean
-	//    default: false
-	//    description: skip TLS verification for registries
-	// responses:
-	//   200:
-	//     schema:
-	//       $ref: "#/definitions/IDResponse"
-	//   400:
-	//     $ref: "#/responses/BadParamError"
-	//   404:
-	//     $ref: "#/responses/NoSuchManifest"
-	//   500:
-	//     $ref: "#/responses/InternalError"
-	v4.Handle("/{name:.*}/registry/{destination:.*}", s.APIHandler(libpod.ManifestPush)).Methods(http.MethodPost)
 	return nil
 }
-- 
cgit v1.2.3-54-g00ecf