github.com/jenkins-x/jx/v2@v2.1.155/pkg/cmd/gc/gc_releases.go (about)

     1  package gc
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/jenkins-x/jx/v2/pkg/cmd/helper"
     7  
     8  	v1 "github.com/jenkins-x/jx-api/pkg/apis/jenkins.io/v1"
     9  	"github.com/jenkins-x/jx/v2/pkg/kube"
    10  	"github.com/spf13/cobra"
    11  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    12  
    13  	"github.com/jenkins-x/jx-logging/pkg/log"
    14  	"github.com/jenkins-x/jx/v2/pkg/cmd/opts"
    15  	"github.com/jenkins-x/jx/v2/pkg/cmd/templates"
    16  )
    17  
    18  // GCReleasesOptions contains the CLI options for this command
    19  type GCReleasesOptions struct {
    20  	*opts.CommonOptions
    21  
    22  	RevisionHistoryLimit int
    23  }
    24  
    25  var (
    26  	GCReleasesLong = templates.LongDesc(`
    27  		Garbage collect the Jenkins X Activity Custom Resource Definitions
    28  
    29  `)
    30  
    31  	GCReleasesExample = templates.Examples(`
    32  		jx garbage collect releases
    33  		jx gc releases
    34  `)
    35  )
    36  
    37  // NewCmd s a command object for the "step" command
    38  func NewCmdGCReleases(commonOpts *opts.CommonOptions) *cobra.Command {
    39  	options := &GCReleasesOptions{
    40  		CommonOptions: commonOpts,
    41  	}
    42  
    43  	cmd := &cobra.Command{
    44  		Use:     "releases",
    45  		Short:   "garbage collection for Releases",
    46  		Long:    GCReleasesLong,
    47  		Example: GCReleasesExample,
    48  		Run: func(cmd *cobra.Command, args []string) {
    49  			options.Cmd = cmd
    50  			options.Args = args
    51  			err := options.Run()
    52  			helper.CheckErr(err)
    53  		},
    54  	}
    55  	cmd.Flags().IntVarP(&options.RevisionHistoryLimit, "revision-history-limit", "l", 5, "Minimum number of Releases per application to keep")
    56  	return cmd
    57  }
    58  
    59  // Run implements this command
    60  func (o *GCReleasesOptions) Run() error {
    61  	err := o.RegisterReleaseCRD()
    62  	if err != nil {
    63  		return err
    64  	}
    65  
    66  	client, ns, err := o.JXClientAndDevNamespace()
    67  	if err != nil {
    68  		return err
    69  	}
    70  
    71  	// cannot use field selectors like `spec.kind=Preview` on CRDs so list all environments
    72  	releaseInterface := client.JenkinsV1().Releases(ns)
    73  	releases, err := releaseInterface.List(metav1.ListOptions{})
    74  	if err != nil {
    75  		return err
    76  	}
    77  	if len(releases.Items) == 0 {
    78  		// no preview environments found so lets return gracefully
    79  		log.Logger().Debug("no releases found")
    80  		return nil
    81  	}
    82  
    83  	jenkinsClient, err := o.JenkinsClient()
    84  	if err != nil {
    85  		return err
    86  	}
    87  	jobs, err := jenkinsClient.GetJobs()
    88  	if err != nil {
    89  		return err
    90  	}
    91  	var jobNames []string
    92  	for _, j := range jobs {
    93  		err = o.GetAllPipelineJobNames(jenkinsClient, &jobNames, j.Name)
    94  		if err != nil {
    95  			return err
    96  		}
    97  	}
    98  
    99  	pipelineReleases := make(map[string][]v1.Release)
   100  
   101  	for _, a := range releases.Items {
   102  		owner := a.Spec.GitOwner
   103  		repo := a.Spec.GitRepository
   104  		pipeline := owner + "/" + repo + "/master"
   105  		// if activity has no job in Jenkins delete it
   106  		matched := true
   107  		if owner != "" && repo != "" {
   108  			matched = false
   109  			for _, j := range jobNames {
   110  				if pipeline == j {
   111  					matched = true
   112  					break
   113  				}
   114  			}
   115  		}
   116  		if !matched {
   117  			err = releaseInterface.Delete(a.Name, metav1.NewDeleteOptions(0))
   118  			if err != nil {
   119  				return err
   120  			} else {
   121  				log.Logger().Infof("Deleting Release %s as it no longer has a pipeline for %s", a.Name, pipeline)
   122  			}
   123  		}
   124  
   125  		// collect all releases for a pipeline
   126  		pipelineReleases[pipeline] = append(pipelineReleases[pipeline], a)
   127  	}
   128  
   129  	for _, releases := range pipelineReleases {
   130  		kube.SortReleases(releases)
   131  
   132  		// iterate over the old releases and remove them
   133  		for i := o.RevisionHistoryLimit + 1; i < len(releases); i++ {
   134  			name := releases[i].Name
   135  			err = releaseInterface.Delete(name, metav1.NewDeleteOptions(0))
   136  			if err != nil {
   137  				return fmt.Errorf("failed to delete Release %s in namespace %s: %v\n", name, ns, err)
   138  			} else {
   139  				log.Logger().Infof("Deleting old Release %s", name)
   140  			}
   141  		}
   142  	}
   143  	return nil
   144  }