// Complete the options for prune images func (o *PruneImagesOptions) Complete(f *clientcmd.Factory, args []string, out io.Writer) error { if len(args) > 0 { return errors.New("no arguments are allowed to this command") } o.Out = out osClient, kClient, registryClient, err := getClients(f, o.CABundle) if err != nil { return err } o.Client = osClient allImages, err := osClient.Images().List(kapi.ListOptions{}) if err != nil { return err } allStreams, err := osClient.ImageStreams(kapi.NamespaceAll).List(kapi.ListOptions{}) if err != nil { return err } allPods, err := kClient.Pods(kapi.NamespaceAll).List(kapi.ListOptions{}) if err != nil { return err } allRCs, err := kClient.ReplicationControllers(kapi.NamespaceAll).List(kapi.ListOptions{}) if err != nil { return err } allBCs, err := osClient.BuildConfigs(kapi.NamespaceAll).List(kapi.ListOptions{}) // We need to tolerate 'not found' errors for buildConfigs since they may be disabled in Atomic err = oserrors.TolerateNotFoundError(err) if err != nil { return err } allBuilds, err := osClient.Builds(kapi.NamespaceAll).List(kapi.ListOptions{}) // We need to tolerate 'not found' errors for builds since they may be disabled in Atomic err = oserrors.TolerateNotFoundError(err) if err != nil { return err } allDCs, err := osClient.DeploymentConfigs(kapi.NamespaceAll).List(kapi.ListOptions{}) if err != nil { return err } options := prune.ImageRegistryPrunerOptions{ KeepYoungerThan: o.KeepYoungerThan, KeepTagRevisions: o.KeepTagRevisions, Images: allImages, Streams: allStreams, Pods: allPods, RCs: allRCs, BCs: allBCs, Builds: allBuilds, DCs: allDCs, DryRun: o.Confirm == false, RegistryClient: registryClient, RegistryURL: o.RegistryUrlOverride, } o.Pruner = prune.NewImageRegistryPruner(options) return nil }
func NewCmdPruneImages(f *clientcmd.Factory, parentName, name string, out io.Writer) *cobra.Command { cfg := &pruneImagesConfig{ Confirm: false, KeepYoungerThan: 60 * time.Minute, KeepTagRevisions: 3, } cmd := &cobra.Command{ Use: name, Short: "Remove unreferenced images", Long: fmt.Sprintf(imagesLongDesc, parentName, name), Run: func(cmd *cobra.Command, args []string) { if len(args) > 0 { glog.Fatal("No arguments are allowed to this command") } osClient, kClient, registryClient, err := getClients(f, cfg) cmdutil.CheckErr(err) allImages, err := osClient.Images().List(labels.Everything(), fields.Everything()) cmdutil.CheckErr(err) allStreams, err := osClient.ImageStreams(kapi.NamespaceAll).List(labels.Everything(), fields.Everything()) cmdutil.CheckErr(err) allPods, err := kClient.Pods(kapi.NamespaceAll).List(labels.Everything(), fields.Everything()) cmdutil.CheckErr(err) allRCs, err := kClient.ReplicationControllers(kapi.NamespaceAll).List(labels.Everything()) cmdutil.CheckErr(err) allBCs, err := osClient.BuildConfigs(kapi.NamespaceAll).List(labels.Everything(), fields.Everything()) cmdutil.CheckErr(err) allBuilds, err := osClient.Builds(kapi.NamespaceAll).List(labels.Everything(), fields.Everything()) cmdutil.CheckErr(err) allDCs, err := osClient.DeploymentConfigs(kapi.NamespaceAll).List(labels.Everything(), fields.Everything()) cmdutil.CheckErr(err) dryRun := cfg.Confirm == false options := prune.ImageRegistryPrunerOptions{ KeepYoungerThan: cfg.KeepYoungerThan, KeepTagRevisions: cfg.KeepTagRevisions, Images: allImages, Streams: allStreams, Pods: allPods, RCs: allRCs, BCs: allBCs, Builds: allBuilds, DCs: allDCs, DryRun: dryRun, RegistryClient: registryClient, RegistryURL: cfg.RegistryUrlOverride, } pruner := prune.NewImageRegistryPruner(options) // this tabwriter is used by the describing*Pruners below for their output w := tabwriter.NewWriter(out, 10, 4, 3, ' ', 0) defer w.Flush() imagePruner := &describingImagePruner{w: w} imageStreamPruner := &describingImageStreamPruner{w: w} layerPruner := &describingLayerPruner{w: w} blobPruner := &describingBlobPruner{w: w} manifestPruner := &describingManifestPruner{w: w} switch cfg.Confirm { case true: imagePruner.delegate = prune.NewDeletingImagePruner(osClient.Images()) imageStreamPruner.delegate = prune.NewDeletingImageStreamPruner(osClient) layerPruner.delegate = prune.NewDeletingLayerPruner() blobPruner.delegate = prune.NewDeletingBlobPruner() manifestPruner.delegate = prune.NewDeletingManifestPruner() default: fmt.Fprintln(os.Stderr, "Dry run enabled - no modifications will be made. Add --confirm to remove images") } err = pruner.Prune(imagePruner, imageStreamPruner, layerPruner, blobPruner, manifestPruner) cmdutil.CheckErr(err) }, } cmd.Flags().BoolVar(&cfg.Confirm, "confirm", cfg.Confirm, "Specify that image pruning should proceed. Defaults to false, displaying what would be deleted but not actually deleting anything.") cmd.Flags().DurationVar(&cfg.KeepYoungerThan, "keep-younger-than", cfg.KeepYoungerThan, "Specify the minimum age of a build for it to be considered a candidate for pruning.") cmd.Flags().IntVar(&cfg.KeepTagRevisions, "keep-tag-revisions", cfg.KeepTagRevisions, "Specify the number of image revisions for a tag in an image stream that will be preserved.") cmd.Flags().StringVar(&cfg.CABundle, "certificate-authority", cfg.CABundle, "The path to a certificate authority bundle to use when communicating with the managed Docker registries. Defaults to the certificate authority data from the current user's config file.") cmd.Flags().StringVar(&cfg.RegistryUrlOverride, "registry-url", cfg.RegistryUrlOverride, "The address to use when contacting the registry, instead of using the default value. This is useful if you can't resolve or reach the registry (e.g.; the default is a cluster-internal URL) but you do have an alternative route that works.") return cmd }