github.com/coreos/rocket@v1.30.1-0.20200224141603-171c416fac02/rkt/image_rm.go (about)

     1  // Copyright 2015 The rkt Authors
     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 main
    16  
    17  import (
    18  	"fmt"
    19  
    20  	"github.com/rkt/rkt/store/imagestore"
    21  	"github.com/spf13/cobra"
    22  )
    23  
    24  var (
    25  	cmdImageRm = &cobra.Command{
    26  		Use:   "rm IMAGE...",
    27  		Short: "Remove one or more images with the given IDs or image names from the local store",
    28  		Long:  `Unlike image gc, image rm allows users to remove specific images.`,
    29  		Run:   runWrapper(runRmImage),
    30  	}
    31  )
    32  
    33  func init() {
    34  	cmdImage.AddCommand(cmdImageRm)
    35  }
    36  
    37  func rmImages(s *imagestore.Store, images []string) error {
    38  	imageMap := make(map[string]string)
    39  
    40  	for _, img := range images {
    41  		key, err := getStoreKeyFromAppOrHash(s, img)
    42  		if err != nil {
    43  			stderr.Error(err)
    44  			continue
    45  		}
    46  
    47  		aciinfo, err := s.GetACIInfoWithBlobKey(key)
    48  		if err != nil {
    49  			stderr.PrintE(fmt.Sprintf("error retrieving aci infos for image %q", key), err)
    50  			continue
    51  		}
    52  
    53  		imageMap[key] = aciinfo.Name
    54  	}
    55  
    56  	done := 0
    57  	errors := 0
    58  	staleErrors := 0
    59  
    60  	for key, name := range imageMap {
    61  		if err := s.RemoveACI(key); err != nil {
    62  			if serr, ok := err.(*imagestore.StoreRemovalError); ok {
    63  				staleErrors++
    64  				stderr.PrintE(fmt.Sprintf("some files cannot be removed for image %q (%q)", key, name), serr)
    65  			} else {
    66  				errors++
    67  				stderr.PrintE(fmt.Sprintf("error removing aci for image %q (%q)", key, name), err)
    68  				continue
    69  			}
    70  		}
    71  		stdout.Printf("successfully removed aci for image: %q", key)
    72  		done++
    73  	}
    74  
    75  	if done > 0 {
    76  		stderr.Printf("%d image(s) successfully removed", done)
    77  	}
    78  
    79  	// If anything didn't complete, return exit status of 1
    80  	if (errors + staleErrors) > 0 {
    81  		if staleErrors > 0 {
    82  			stderr.Printf("%d image(s) removed but left some stale files", staleErrors)
    83  		}
    84  		if errors > 0 {
    85  			stderr.Printf("%d image(s) cannot be removed", errors)
    86  		}
    87  		return fmt.Errorf("error(s) found while removing images")
    88  	}
    89  
    90  	return nil
    91  }
    92  
    93  func runRmImage(cmd *cobra.Command, args []string) (exit int) {
    94  	if len(args) < 1 {
    95  		stderr.Print("must provide at least one image ID")
    96  		return 254
    97  	}
    98  
    99  	s, err := imagestore.NewStore(storeDir())
   100  	if err != nil {
   101  		stderr.PrintE("cannot open store", err)
   102  		return 254
   103  	}
   104  
   105  	if err := rmImages(s, args); err != nil {
   106  		stderr.Error(err)
   107  		return 254
   108  	}
   109  
   110  	return 0
   111  }