func (l *buildLoader) Load() error { list, err := l.lister.Builds(l.namespace).List(kapi.ListOptions{}) if err != nil { return errors.TolerateNotFoundError(err) } l.items = list.Items return nil }
func (l *buildLoader) Load() error { list, err := l.lister.Builds(l.namespace).List(labels.Everything(), fields.Everything()) if err != nil { return errors.TolerateNotFoundError(err) } l.items = list.Items return nil }
func waitForEndpointsAvailable(oc *exutil.CLI, serviceName string) error { return wait.Poll(200*time.Millisecond, 2*time.Minute, func() (bool, error) { ep, err := oc.KubeClient().Core().Endpoints(oc.Namespace()).Get(serviceName) // Tolerate NotFound b/c it could take a moment for the endpoints to be created if errors.TolerateNotFoundError(err) != nil { return false, err } return (len(ep.Subsets) > 0) && (len(ep.Subsets[0].Addresses) > 0), nil }) }
// findScalableResourcesForEndpoints takes an Endpoints object and looks for the associated // scalable objects by checking each address in each subset to see if it has a pod // reference, and the following that pod reference to find the owning controller, // and returning the unique set of controllers found this way. func findScalableResourcesForEndpoints(endpoints *kapi.Endpoints, decoder runtime.Decoder, getPod func(kapi.ObjectReference) (*kapi.Pod, error), getController func(kapi.ObjectReference) (runtime.Object, error)) (map[unidlingapi.CrossGroupObjectReference]struct{}, error) { // To find all RCs and DCs for an endpoint, we first figure out which pods are pointed to by that endpoint... podRefs := map[kapi.ObjectReference]*kapi.Pod{} for _, subset := range endpoints.Subsets { for _, addr := range subset.Addresses { if addr.TargetRef != nil && addr.TargetRef.Kind == "Pod" { pod, err := getPod(*addr.TargetRef) if utilerrors.TolerateNotFoundError(err) != nil { return nil, fmt.Errorf("unable to find controller for pod %s/%s: %v", addr.TargetRef.Namespace, addr.TargetRef.Name, err) } if pod != nil { podRefs[*addr.TargetRef] = pod } } } } // ... then, for each pod, we check the controller, and find the set of unique controllers... immediateControllerRefs := make(map[kapi.ObjectReference]struct{}) for _, pod := range podRefs { controllerRef, err := getControllerRef(pod, decoder) if err != nil { return nil, fmt.Errorf("unable to find controller for pod %s/%s: %v", pod.Namespace, pod.Name, err) } else if controllerRef == nil { return nil, fmt.Errorf("unable to find controller for pod %s/%s: no creator reference listed", pod.Namespace, pod.Name) } immediateControllerRefs[*controllerRef] = struct{}{} } // ... finally, for each controller, we load it, and see if there is a corresponding owner (to cover cases like DCs, Deployments, etc) controllerRefs := make(map[unidlingapi.CrossGroupObjectReference]struct{}) for controllerRef := range immediateControllerRefs { controller, err := getController(controllerRef) if utilerrors.TolerateNotFoundError(err) != nil { return nil, fmt.Errorf("unable to load %s %q: %v", controllerRef.Kind, controllerRef.Name, err) } if controller != nil { var parentControllerRef *kapi.ObjectReference parentControllerRef, err = getControllerRef(controller, decoder) if err != nil { return nil, fmt.Errorf("unable to load the creator of %s %q: %v", controllerRef.Kind, controllerRef.Name, err) } var crossGroupObjRef unidlingapi.CrossGroupObjectReference if parentControllerRef == nil { // if this is just a plain RC, use it crossGroupObjRef, err = makeCrossGroupObjRef(&controllerRef) } else { crossGroupObjRef, err = makeCrossGroupObjRef(parentControllerRef) } if err != nil { return nil, fmt.Errorf("unable to load the creator of %s %q: %v", controllerRef.Kind, controllerRef.Name, err) } controllerRefs[crossGroupObjRef] = struct{}{} } } return controllerRefs, nil }
// 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 }
// Run contains all the necessary functionality for the OpenShift cli prune images command. func (o PruneImagesOptions) Run() error { allImages, err := o.OSClient.Images().List(kapi.ListOptions{}) if err != nil { return err } allStreams, err := o.OSClient.ImageStreams(o.Namespace).List(kapi.ListOptions{}) if err != nil { return err } allPods, err := o.KClient.Core().Pods(o.Namespace).List(kapi.ListOptions{}) if err != nil { return err } allRCs, err := o.KClient.Core().ReplicationControllers(o.Namespace).List(kapi.ListOptions{}) if err != nil { return err } allBCs, err := o.OSClient.BuildConfigs(o.Namespace).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 := o.OSClient.Builds(o.Namespace).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 := o.OSClient.DeploymentConfigs(o.Namespace).List(kapi.ListOptions{}) if err != nil { return err } limitRangesList, err := o.KClient.Core().LimitRanges(o.Namespace).List(kapi.ListOptions{}) if err != nil { return err } limitRangesMap := make(map[string][]*kapi.LimitRange) for i := range limitRangesList.Items { limit := limitRangesList.Items[i] limits, ok := limitRangesMap[limit.Namespace] if !ok { limits = []*kapi.LimitRange{} } limits = append(limits, &limit) limitRangesMap[limit.Namespace] = limits } options := prune.PrunerOptions{ KeepYoungerThan: o.KeepYoungerThan, KeepTagRevisions: o.KeepTagRevisions, PruneOverSizeLimit: o.PruneOverSizeLimit, AllImages: o.AllImages, Images: allImages, Streams: allStreams, Pods: allPods, RCs: allRCs, BCs: allBCs, Builds: allBuilds, DCs: allDCs, LimitRanges: limitRangesMap, DryRun: o.Confirm == false, RegistryClient: o.RegistryClient, RegistryURL: o.RegistryUrlOverride, } if o.Namespace != kapi.NamespaceAll { options.Namespace = o.Namespace } pruner := prune.NewPruner(options) w := tabwriter.NewWriter(o.Out, 10, 4, 3, ' ', 0) defer w.Flush() imageDeleter := &describingImageDeleter{w: w} imageStreamDeleter := &describingImageStreamDeleter{w: w} layerLinkDeleter := &describingLayerLinkDeleter{w: w} blobDeleter := &describingBlobDeleter{w: w} manifestDeleter := &describingManifestDeleter{w: w} if o.Confirm { imageDeleter.delegate = prune.NewImageDeleter(o.OSClient.Images()) imageStreamDeleter.delegate = prune.NewImageStreamDeleter(o.OSClient) layerLinkDeleter.delegate = prune.NewLayerLinkDeleter() blobDeleter.delegate = prune.NewBlobDeleter() manifestDeleter.delegate = prune.NewManifestDeleter() } else { fmt.Fprintln(os.Stderr, "Dry run enabled - no modifications will be made. Add --confirm to remove images") } return pruner.Prune(imageDeleter, imageStreamDeleter, layerLinkDeleter, blobDeleter, manifestDeleter) }
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()) // We need to tolerate 'not found' errors for buildConfigs since they may be disabled in Atomic err = oserrors.TolerateNotFoundError(err) cmdutil.CheckErr(err) allBuilds, err := osClient.Builds(kapi.NamespaceAll).List(labels.Everything(), fields.Everything()) // We need to tolerate 'not found' errors for builds since they may be disabled in Atomic err = oserrors.TolerateNotFoundError(err) 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 }
// Complete turns a partially defined PruneImagesOptions into a solvent structure // which can be validated and used for pruning images. func (o *PruneImagesOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, args []string, out io.Writer) error { if len(args) > 0 { return kcmdutil.UsageError(cmd, "no arguments are allowed to this command") } if !cmd.Flags().Lookup("keep-younger-than").Changed { o.KeepYoungerThan = nil } if !cmd.Flags().Lookup("keep-tag-revisions").Changed { o.KeepTagRevisions = nil } if !cmd.Flags().Lookup("prune-over-size-limit").Changed { o.PruneOverSizeLimit = nil } 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 } limitRangesList, err := kClient.LimitRanges(kapi.NamespaceAll).List(kapi.ListOptions{}) if err != nil { return err } limitRangesMap := make(map[string][]*kapi.LimitRange) for i := range limitRangesList.Items { limit := limitRangesList.Items[i] limits, ok := limitRangesMap[limit.Namespace] if !ok { limits = []*kapi.LimitRange{} } limits = append(limits, &limit) limitRangesMap[limit.Namespace] = limits } options := prune.PrunerOptions{ KeepYoungerThan: o.KeepYoungerThan, KeepTagRevisions: o.KeepTagRevisions, PruneOverSizeLimit: o.PruneOverSizeLimit, Images: allImages, Streams: allStreams, Pods: allPods, RCs: allRCs, BCs: allBCs, Builds: allBuilds, DCs: allDCs, LimitRanges: limitRangesMap, DryRun: o.Confirm == false, RegistryClient: registryClient, RegistryURL: o.RegistryUrlOverride, } o.Pruner = prune.NewPruner(options) return nil }