github.com/opencontainers/umoci@v0.4.8-0.20240508124516-656e4836fb0d/cmd/umoci/unpack.go (about)

     1  /*
     2   * umoci: Umoci Modifies Open Containers' Images
     3   * Copyright (C) 2016-2020 SUSE LLC
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *    http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  package main
    19  
    20  import (
    21  	"github.com/opencontainers/umoci"
    22  	"github.com/opencontainers/umoci/oci/cas/dir"
    23  	"github.com/opencontainers/umoci/oci/casext"
    24  	"github.com/opencontainers/umoci/oci/layer"
    25  	"github.com/pkg/errors"
    26  	"github.com/urfave/cli"
    27  )
    28  
    29  var unpackCommand = uxRemap(cli.Command{
    30  	Name:  "unpack",
    31  	Usage: "unpacks a reference into an OCI runtime bundle",
    32  	ArgsUsage: `--image <image-path>[:<tag>] <bundle>
    33  
    34  Where "<image-path>" is the path to the OCI image, "<tag>" is the name of the
    35  tagged image to unpack (if not specified, defaults to "latest") and "<bundle>"
    36  is the destination to unpack the image to.
    37  
    38  It should be noted that this is not the same as oci-create-runtime-bundle,
    39  because this command also will create an mtree specification to allow for layer
    40  creation with umoci-repack(1).`,
    41  
    42  	// unpack reads manifest information.
    43  	Category: "image",
    44  
    45  	Flags: []cli.Flag{
    46  		cli.BoolFlag{
    47  			Name:  "keep-dirlinks",
    48  			Usage: "don't clobber underlying symlinks to directories",
    49  		},
    50  	},
    51  
    52  	Action: unpack,
    53  
    54  	Before: func(ctx *cli.Context) error {
    55  		if ctx.NArg() != 1 {
    56  			return errors.Errorf("invalid number of positional arguments: expected <bundle>")
    57  		}
    58  		if ctx.Args().First() == "" {
    59  			return errors.Errorf("bundle path cannot be empty")
    60  		}
    61  		ctx.App.Metadata["bundle"] = ctx.Args().First()
    62  		return nil
    63  	},
    64  })
    65  
    66  func unpack(ctx *cli.Context) error {
    67  	imagePath := ctx.App.Metadata["--image-path"].(string)
    68  	fromName := ctx.App.Metadata["--image-tag"].(string)
    69  	bundlePath := ctx.App.Metadata["bundle"].(string)
    70  
    71  	var unpackOptions layer.UnpackOptions
    72  	var meta umoci.Meta
    73  	meta.Version = umoci.MetaVersion
    74  
    75  	// Parse and set up the mapping options.
    76  	err := umoci.ParseIdmapOptions(&meta, ctx)
    77  	if err != nil {
    78  		return err
    79  	}
    80  
    81  	unpackOptions.KeepDirlinks = ctx.Bool("keep-dirlinks")
    82  	unpackOptions.MapOptions = meta.MapOptions
    83  
    84  	// Get a reference to the CAS.
    85  	engine, err := dir.Open(imagePath)
    86  	if err != nil {
    87  		return errors.Wrap(err, "open CAS")
    88  	}
    89  	engineExt := casext.NewEngine(engine)
    90  	defer engine.Close()
    91  	return umoci.Unpack(engineExt, fromName, bundlePath, unpackOptions)
    92  }