github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/pkg/task/display.go (about)

     1  package task
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"log"
     7  	"os"
     8  	"strings"
     9  
    10  	"github.com/spf13/cobra"
    11  	"github.com/turbot/go-kit/files"
    12  	"github.com/turbot/steampipe/pkg/error_helpers"
    13  	"github.com/turbot/steampipe/pkg/filepaths"
    14  	"github.com/turbot/steampipe/pkg/plugin"
    15  	"github.com/turbot/steampipe/pkg/utils"
    16  )
    17  
    18  const (
    19  	AvailableVersionsCacheStructVersion = 20230117
    20  )
    21  
    22  func (r *Runner) saveAvailableVersions(cli *CLIVersionCheckResponse, plugin map[string]plugin.VersionCheckReport) error {
    23  	utils.LogTime("Runner.saveAvailableVersions start")
    24  	defer utils.LogTime("Runner.saveAvailableVersions end")
    25  
    26  	if cli == nil && len(plugin) == 0 {
    27  		// nothing to save
    28  		return nil
    29  	}
    30  
    31  	notifs := &AvailableVersionCache{
    32  		StructVersion: AvailableVersionsCacheStructVersion,
    33  		CliCache:      cli,
    34  		PluginCache:   plugin,
    35  	}
    36  	// create the file - if it exists, it will be truncated by os.Create
    37  	f, err := os.Create(filepaths.AvailableVersionsFilePath())
    38  	if err != nil {
    39  		return err
    40  	}
    41  	defer f.Close()
    42  	encoder := json.NewEncoder(f)
    43  	return encoder.Encode(notifs)
    44  }
    45  
    46  func (r *Runner) hasAvailableVersion() bool {
    47  	utils.LogTime("Runner.hasNotifications start")
    48  	defer utils.LogTime("Runner.hasNotifications end")
    49  	return files.FileExists(filepaths.AvailableVersionsFilePath())
    50  }
    51  
    52  func (r *Runner) loadCachedVersions() (*AvailableVersionCache, error) {
    53  	utils.LogTime("Runner.getNotifications start")
    54  	defer utils.LogTime("Runner.getNotifications end")
    55  	f, err := os.Open(filepaths.AvailableVersionsFilePath())
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  	notifications := &AvailableVersionCache{}
    60  	decoder := json.NewDecoder(f)
    61  	if err := decoder.Decode(notifications); err != nil {
    62  		return nil, err
    63  	}
    64  	if err := error_helpers.CombineErrors(f.Close(), os.Remove(filepaths.AvailableVersionsFilePath())); err != nil {
    65  		// if Go couldn't close the file handle, no matter - this was just good practise
    66  		// if Go couldn't remove the notification file, it'll get truncated next time we try to write to it
    67  		// worst case is that the notification gets shown more than once
    68  		log.Println("[TRACE] could not close/delete notification file", err)
    69  	}
    70  	return notifications, nil
    71  }
    72  
    73  // displayNotifications checks if there are any pending notifications to display
    74  // and if so, displays them
    75  // does nothing if the given command is a command where notifications are not displayed
    76  func (r *Runner) displayNotifications(cmd *cobra.Command, cmdArgs []string) error {
    77  	utils.LogTime("Runner.displayNotifications start")
    78  	defer utils.LogTime("Runner.displayNotifications end")
    79  
    80  	ctx := cmd.Context()
    81  
    82  	if !showNotificationsForCommand(cmd, cmdArgs) {
    83  		// do not do anything - just return
    84  		return nil
    85  	}
    86  
    87  	if !r.hasAvailableVersion() {
    88  		// nothing to display
    89  		return nil
    90  	}
    91  
    92  	cachedVersions, err := r.loadCachedVersions()
    93  	if err != nil {
    94  		return err
    95  	}
    96  
    97  	tableBuffer, err := cachedVersions.asTable(ctx)
    98  	if err != nil {
    99  		return err
   100  	}
   101  	// get the buffer width (to set the column width of ppTable)
   102  	lineLength := len(strings.Split(tableBuffer.String(), "\n")[0])
   103  
   104  	ppTable, err := ppNoptificationAsTable(lineLength)
   105  	if err != nil {
   106  		return err
   107  	}
   108  
   109  	// table can be nil if there are no notifications to display
   110  	if tableBuffer != nil {
   111  		fmt.Println()            //nolint:forbidigo // acceptable
   112  		fmt.Println(tableBuffer) //nolint:forbidigo // acceptable
   113  	}
   114  
   115  	if ppTable != nil {
   116  		ppTable.Render()
   117  		fmt.Println() //nolint:forbidigo // acceptable
   118  	}
   119  
   120  	return nil
   121  }