@ -14,12 +14,19 @@ limitations under the License.
package main
import (
"fmt"
"io"
"os"
"strings"
"github.com/gosuri/uitable"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"helm.sh/helm/v3/cmd/helm/require"
"helm.sh/helm/v3/cmd/helm/search"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/cli/output"
"helm.sh/helm/v3/pkg/release"
)
var outdatedHelp = `
@ -40,13 +47,125 @@ func newOutdatedCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Aliases : [ ] string { "od" } ,
Args : require . NoArgs ,
RunE : func ( cmd * cobra . Command , args [ ] string ) error {
return nil
if client . AllNamespaces {
if err := cfg . Init ( settings . RESTClientGetter ( ) , "" , os . Getenv ( "HELM_DRIVER" ) , debug ) ; err != nil {
return err
}
}
client . SetStateMask ( )
releases , err := client . Run ( )
if err != nil {
return err
}
devel , err := cmd . Flags ( ) . GetBool ( "devel" )
if err != nil {
return err
}
return outfmt . Write ( out , newOutdatedListWriter ( releases , cfg , out , devel ) )
} ,
}
flags := cmd . Flags ( )
flags . BoolVarP ( & client . AllNamespaces , "all-namespaces" , "A" , false , "list releases across all namespaces" )
flags . Bool ( "devel" , false , "use development versions (alpha, beta, and release candidate releases), too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored" )
bindOutputFlag ( cmd , & outfmt )
return cmd
}
type outdatedElement struct {
Name string ` json:"name" `
Namespace string ` json:"namespace" `
InstalledVer string ` json:"installed_version" `
LatestVer string ` json:"latest_version" `
Chart string ` json:"chart" `
}
type outdatedListWriter struct {
releases [ ] outdatedElement // Outdated releases
}
func newOutdatedListWriter ( releases [ ] * release . Release , cfg * action . Configuration , out io . Writer , devel bool ) * outdatedListWriter {
outdated := make ( [ ] outdatedElement , 0 , len ( releases ) )
// we initialize the Struct with default Options but the 'devel' option
// can be set by the User, all the other ones are not relevant.
searchRepo := searchRepoOptions {
versions : false ,
regexp : false ,
devel : devel ,
maxColWidth : 50 ,
version : "" ,
}
// initialize Repo index first
index , err := initSearch ( out , & searchRepo )
if err != nil {
// TODO: Find a better way to exit
fmt . Errorf ( "%w" , errors . Wrap ( err , "ERROR: Could not initialize search index." ) )
}
results := index . All ( )
for _ , r := range releases {
// search if it exists a newer Chart in the Chart-Repository
repoResult , err := searchChart ( results , r . Name )
if err != nil {
fmt . Errorf ( "%w" , errors . Wrap ( err , "ERROR: Could not initialize search index." ) )
}
outdated = append ( outdated , outdatedElement {
Name : r . Name ,
Namespace : r . Namespace ,
InstalledVer : r . Chart . Metadata . Version ,
LatestVer : repoResult . Chart . Metadata . Version ,
Chart : repoResult . Chart . Name ,
} )
}
return & outdatedListWriter { outdated }
}
func initSearch ( out io . Writer , o * searchRepoOptions ) ( * search . Index , error ) {
index , err := o . buildIndex ( out )
if err != nil {
return nil , err
}
return index , nil
}
// searchChart searches for Repositories which are containing that chart.
//
// It will return a Pointer to the Chart Result (the Pointer points to the
// Result of the Index).
// If no results are found, nil will be returned instead of type *Result.
func searchChart ( r [ ] * search . Result , name string ) ( * search . Result , error ) {
// TODO: implement a better Searchalgorithm.
for _ , result := range r {
if strings . ToLower ( result . Name ) == strings . ToLower ( name ) {
return result , nil
}
}
debug ( "Could not find any Repo which contains %s" , name )
return nil , errors . New ( fmt . Sprintf ( "Could not find any Repo which contains %s" , name ) )
}
func ( r * outdatedListWriter ) WriteTable ( out io . Writer ) error {
table := uitable . New ( )
table . AddRow ( "NAME" , "NAMESPACE" , "INSTALLED VERSION" , "LATEST VERSION" , "CHART" )
for _ , r := range r . releases {
table . AddRow ( r . Name , r . Namespace , r . InstalledVer , r . LatestVer , r . Chart )
}
return output . EncodeTable ( out , table )
}
func ( r * outdatedListWriter ) WriteJSON ( out io . Writer ) error {
return output . EncodeJSON ( out , r . releases )
}
func ( r * outdatedListWriter ) WriteYAML ( out io . Writer ) error {
return output . EncodeYAML ( out , r . releases )
}