Merge pull request #5656 from baude/v2imagetag
podman v2 image tag and untag
This commit is contained in:
		
						commit
						82cbebcbea
					
				|  | @ -0,0 +1,34 @@ | |||
| package images | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/containers/libpod/cmd/podmanV2/registry" | ||||
| 	"github.com/containers/libpod/pkg/domain/entities" | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	tagDescription = "Adds one or more additional names to locally-stored image." | ||||
| 	tagCommand     = &cobra.Command{ | ||||
| 		Use:   "tag [flags] IMAGE TARGET_NAME [TARGET_NAME...]", | ||||
| 		Short: "Add an additional name to a local image", | ||||
| 		Long:  tagDescription, | ||||
| 		RunE:  tag, | ||||
| 		Args:  cobra.MinimumNArgs(2), | ||||
| 		Example: `podman tag 0e3bbc2 fedora:latest | ||||
|   podman tag imageID:latest myNewImage:newTag | ||||
|   podman tag httpd myregistryhost:5000/fedora/httpd:v2`, | ||||
| 	} | ||||
| ) | ||||
| 
 | ||||
| func init() { | ||||
| 	registry.Commands = append(registry.Commands, registry.CliCommand{ | ||||
| 		Mode:    []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, | ||||
| 		Command: tagCommand, | ||||
| 	}) | ||||
| 	tagCommand.SetHelpTemplate(registry.HelpTemplate()) | ||||
| 	tagCommand.SetUsageTemplate(registry.UsageTemplate()) | ||||
| } | ||||
| 
 | ||||
| func tag(cmd *cobra.Command, args []string) error { | ||||
| 	return registry.ImageEngine().Tag(registry.GetContext(), args[0], args[1:], entities.ImageTagOptions{}) | ||||
| } | ||||
|  | @ -0,0 +1,33 @@ | |||
| package images | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/containers/libpod/cmd/podmanV2/registry" | ||||
| 	"github.com/containers/libpod/pkg/domain/entities" | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	untagCommand = &cobra.Command{ | ||||
| 		Use:   "untag [flags] IMAGE [NAME...]", | ||||
| 		Short: "Remove a name from a local image", | ||||
| 		Long:  "Removes one or more names from a locally-stored image.", | ||||
| 		RunE:  untag, | ||||
| 		Args:  cobra.MinimumNArgs(1), | ||||
| 		Example: `podman untag 0e3bbc2 | ||||
|   podman untag imageID:latest otherImageName:latest | ||||
|   podman untag httpd myregistryhost:5000/fedora/httpd:v2`, | ||||
| 	} | ||||
| ) | ||||
| 
 | ||||
| func init() { | ||||
| 	registry.Commands = append(registry.Commands, registry.CliCommand{ | ||||
| 		Mode:    []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, | ||||
| 		Command: untagCommand, | ||||
| 	}) | ||||
| 	untagCommand.SetHelpTemplate(registry.HelpTemplate()) | ||||
| 	untagCommand.SetUsageTemplate(registry.UsageTemplate()) | ||||
| } | ||||
| 
 | ||||
| func untag(cmd *cobra.Command, args []string) error { | ||||
| 	return registry.ImageEngine().Untag(registry.GetContext(), args[0], args[1:], entities.ImageUntagOptions{}) | ||||
| } | ||||
|  | @ -510,3 +510,29 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) { | |||
| 	} | ||||
| 	utils.WriteResponse(w, http.StatusOK, handlers.IDResponse{ID: commitImage.ID()}) // nolint
 | ||||
| } | ||||
| 
 | ||||
| func UntagImage(w http.ResponseWriter, r *http.Request) { | ||||
| 	runtime := r.Context().Value("runtime").(*libpod.Runtime) | ||||
| 
 | ||||
| 	name := utils.GetName(r) | ||||
| 	newImage, err := runtime.ImageRuntime().NewFromLocal(name) | ||||
| 	if err != nil { | ||||
| 		utils.ImageNotFound(w, name, errors.Wrapf(err, "Failed to find image %s", name)) | ||||
| 		return | ||||
| 	} | ||||
| 	tag := "latest" | ||||
| 	if len(r.Form.Get("tag")) > 0 { | ||||
| 		tag = r.Form.Get("tag") | ||||
| 	} | ||||
| 	if len(r.Form.Get("repo")) < 1 { | ||||
| 		utils.Error(w, "repo tag is required", http.StatusBadRequest, errors.New("repo parameter is required to tag an image")) | ||||
| 		return | ||||
| 	} | ||||
| 	repo := r.Form.Get("repo") | ||||
| 	tagName := fmt.Sprintf("%s:%s", repo, tag) | ||||
| 	if err := newImage.UntagImage(tagName); err != nil { | ||||
| 		utils.Error(w, "failed to untag", http.StatusInternalServerError, err) | ||||
| 		return | ||||
| 	} | ||||
| 	utils.WriteResponse(w, http.StatusCreated, "") | ||||
| } | ||||
|  |  | |||
|  | @ -1019,5 +1019,39 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { | |||
| 	//   500:
 | ||||
| 	//     $ref: '#/responses/InternalError'
 | ||||
| 	r.Handle(VersionedPath("/libpod/commit"), s.APIHandler(libpod.CommitContainer)).Methods(http.MethodPost) | ||||
| 	// swagger:operation POST /libpod/images/{name:.*}/untag libpod libpodUntagImage
 | ||||
| 	// ---
 | ||||
| 	// tags:
 | ||||
| 	//  - images
 | ||||
| 	// summary: Untag an image
 | ||||
| 	// description: Untag an image
 | ||||
| 	// parameters:
 | ||||
| 	//  - in: path
 | ||||
| 	//    name: name:.*
 | ||||
| 	//    type: string
 | ||||
| 	//    required: true
 | ||||
| 	//    description: the name or ID of the container
 | ||||
| 	//  - in: query
 | ||||
| 	//    name: repo
 | ||||
| 	//    type: string
 | ||||
| 	//    description: the repository to untag
 | ||||
| 	//  - in: query
 | ||||
| 	//    name: tag
 | ||||
| 	//    type: string
 | ||||
| 	//    description: the name of the tag to untag
 | ||||
| 	// produces:
 | ||||
| 	// - application/json
 | ||||
| 	// responses:
 | ||||
| 	//   201:
 | ||||
| 	//     description: no error
 | ||||
| 	//   400:
 | ||||
| 	//     $ref: '#/responses/BadParamError'
 | ||||
| 	//   404:
 | ||||
| 	//     $ref: '#/responses/NoSuchImage'
 | ||||
| 	//   409:
 | ||||
| 	//     $ref: '#/responses/ConflictError'
 | ||||
| 	//   500:
 | ||||
| 	//     $ref: '#/responses/InternalError'
 | ||||
| 	r.Handle(VersionedPath("/libpod/images/{name:.*}/untag"), s.APIHandler(libpod.UntagImage)).Methods(http.MethodPost) | ||||
| 	return nil | ||||
| } | ||||
|  |  | |||
|  | @ -197,6 +197,22 @@ func Tag(ctx context.Context, nameOrID, tag, repo string) error { | |||
| 	return response.Process(nil) | ||||
| } | ||||
| 
 | ||||
| // Untag removes a name from locally-stored image. Both the tag and repo parameters are required.
 | ||||
| func Untag(ctx context.Context, nameOrID, tag, repo string) error { | ||||
| 	conn, err := bindings.GetClient(ctx) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	params := url.Values{} | ||||
| 	params.Set("tag", tag) | ||||
| 	params.Set("repo", repo) | ||||
| 	response, err := conn.DoRequest(nil, http.MethodPost, "/images/%s/untag", params, nameOrID) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return response.Process(nil) | ||||
| } | ||||
| 
 | ||||
| func Build(nameOrId string) {} | ||||
| 
 | ||||
| // Imports adds the given image to the local image store.  This can be done by file and the given reader
 | ||||
|  |  | |||
|  | @ -11,4 +11,6 @@ type ImageEngine interface { | |||
| 	List(ctx context.Context, opts ImageListOptions) ([]*ImageSummary, error) | ||||
| 	Prune(ctx context.Context, opts ImagePruneOptions) (*ImagePruneReport, error) | ||||
| 	Pull(ctx context.Context, rawImage string, opts ImagePullOptions) (*ImagePullReport, error) | ||||
| 	Tag(ctx context.Context, nameOrId string, tags []string, options ImageTagOptions) error | ||||
| 	Untag(ctx context.Context, nameOrId string, tags []string, options ImageUntagOptions) error | ||||
| } | ||||
|  |  | |||
|  | @ -171,3 +171,6 @@ type ImagePruneReport struct { | |||
| 	Report Report | ||||
| 	Size   int64 | ||||
| } | ||||
| 
 | ||||
| type ImageTagOptions struct{} | ||||
| type ImageUntagOptions struct{} | ||||
|  |  | |||
|  | @ -264,3 +264,28 @@ func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, options entiti | |||
| // 	copy(report.Report.Id, id)
 | ||||
| // 	return &report, nil
 | ||||
| // }
 | ||||
| 
 | ||||
| func (ir *ImageEngine) Tag(ctx context.Context, nameOrId string, tags []string, options entities.ImageTagOptions) error { | ||||
| 	newImage, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	for _, tag := range tags { | ||||
| 		if err := newImage.TagImage(tag); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| func (ir *ImageEngine) Untag(ctx context.Context, nameOrId string, tags []string, options entities.ImageUntagOptions) error { | ||||
| 	newImage, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	for _, tag := range tags { | ||||
| 		if err := newImage.UntagImage(tag); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  |  | |||
|  | @ -3,9 +3,11 @@ package tunnel | |||
| import ( | ||||
| 	"context" | ||||
| 
 | ||||
| 	"github.com/containers/image/v5/docker/reference" | ||||
| 	images "github.com/containers/libpod/pkg/bindings/images" | ||||
| 	"github.com/containers/libpod/pkg/domain/entities" | ||||
| 	"github.com/containers/libpod/pkg/domain/utils" | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
| 
 | ||||
| func (ir *ImageEngine) Exists(_ context.Context, nameOrId string) (*entities.BoolReport, error) { | ||||
|  | @ -93,3 +95,53 @@ func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, options entiti | |||
| 	} | ||||
| 	return &entities.ImagePullReport{Images: pulledImages}, nil | ||||
| } | ||||
| 
 | ||||
| func (ir *ImageEngine) Tag(ctx context.Context, nameOrId string, tags []string, options entities.ImageTagOptions) error { | ||||
| 	for _, newTag := range tags { | ||||
| 		var ( | ||||
| 			tag, repo string | ||||
| 		) | ||||
| 		ref, err := reference.Parse(newTag) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if t, ok := ref.(reference.Tagged); ok { | ||||
| 			tag = t.Tag() | ||||
| 		} | ||||
| 		if r, ok := ref.(reference.Named); ok { | ||||
| 			repo = r.Name() | ||||
| 		} | ||||
| 		if len(repo) < 1 { | ||||
| 			return errors.Errorf("invalid image name %q", nameOrId) | ||||
| 		} | ||||
| 		if err := images.Tag(ir.ClientCxt, nameOrId, tag, repo); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (ir *ImageEngine) Untag(ctx context.Context, nameOrId string, tags []string, options entities.ImageUntagOptions) error { | ||||
| 	for _, newTag := range tags { | ||||
| 		var ( | ||||
| 			tag, repo string | ||||
| 		) | ||||
| 		ref, err := reference.Parse(newTag) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if t, ok := ref.(reference.Tagged); ok { | ||||
| 			tag = t.Tag() | ||||
| 		} | ||||
| 		if r, ok := ref.(reference.Named); ok { | ||||
| 			repo = r.Name() | ||||
| 		} | ||||
| 		if len(repo) < 1 { | ||||
| 			return errors.Errorf("invalid image name %q", nameOrId) | ||||
| 		} | ||||
| 		if err := images.Untag(ir.ClientCxt, nameOrId, tag, repo); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue