github.com/mgoltzsche/ctnr@v0.7.1-alpha/cmd/commit.go (about)

     1  // Copyright © 2017 Max Goltzsche
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package cmd
    16  
    17  import (
    18  	"fmt"
    19  	"path/filepath"
    20  
    21  	"github.com/mgoltzsche/ctnr/image"
    22  	"github.com/mgoltzsche/ctnr/pkg/fs/tree"
    23  	"github.com/opencontainers/go-digest"
    24  	"github.com/pkg/errors"
    25  	"github.com/spf13/cobra"
    26  )
    27  
    28  var (
    29  	commitCmd = &cobra.Command{
    30  		Use:   "commit [flags] CONTAINER [IMAGENAME]",
    31  		Short: "Creates a new image from the current container",
    32  		Long:  `Creates a new image from the current container.`,
    33  		Run:   wrapRun(runCommit),
    34  	}
    35  	flagAuthor  string
    36  	flagComment string
    37  )
    38  
    39  func init() {
    40  	commitCmd.Flags().StringVarP(&flagAuthor, "author", "a", "", "Sets the new layer's author")
    41  	commitCmd.Flags().StringVarP(&flagComment, "comment", "c", "", "Sets the new layer's comment")
    42  }
    43  
    44  func runCommit(cmd *cobra.Command, args []string) (err error) {
    45  	if len(args) < 1 || len(args) > 2 {
    46  		return usageError("Invalid argument")
    47  	}
    48  	bundleId := args[0]
    49  	b, err := store.Bundle(bundleId)
    50  	if err != nil {
    51  		return
    52  	}
    53  	lockedBundle, err := b.Lock()
    54  	if err != nil {
    55  		return
    56  	}
    57  	defer lockedBundle.Close()
    58  	lockedStore, err := openImageStore()
    59  	if err != nil {
    60  		return
    61  	}
    62  	spec, err := lockedBundle.Spec()
    63  	if err != nil {
    64  		return
    65  	}
    66  	if spec.Root == nil {
    67  		return errors.Errorf("bundle %q has no root path", bundleId)
    68  	}
    69  	rootfs, err := tree.FromDir(filepath.Join(b.Dir(), spec.Root.Path), flagRootless)
    70  	if err != nil {
    71  		return
    72  	}
    73  
    74  	// Try to create new image
    75  	var (
    76  		imgId digest.Digest
    77  		img   image.Image
    78  	)
    79  	if flagComment == "" {
    80  		flagComment = "commit"
    81  	}
    82  	if img, err = lockedStore.AddLayer(rootfs, lockedBundle.Image(), flagAuthor, flagComment); err == nil {
    83  		imgId = img.ID()
    84  		err = lockedBundle.SetParentImageId(&imgId)
    85  	} else if image.IsEmptyLayerDiff(err) {
    86  		bImgId := lockedBundle.Image()
    87  		if bImgId == nil {
    88  			panic("bundle has no parent but provides no layer contents")
    89  		}
    90  		imgId = *bImgId
    91  		err = nil
    92  	}
    93  
    94  	// Tag image
    95  	if err == nil {
    96  		if len(args) > 1 {
    97  			for _, tag := range args[1:] {
    98  				if _, err = lockedStore.TagImage(imgId, tag); err != nil {
    99  					return
   100  				}
   101  			}
   102  		}
   103  		fmt.Println(imgId)
   104  	}
   105  	return
   106  }