github.com/Racer159/jackal@v0.32.7-0.20240401174413-0bd2339e4f2e/src/pkg/packager/interactive.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // SPDX-FileCopyrightText: 2021-Present The Jackal Authors
     3  
     4  // Package packager contains functions for interacting with, managing and deploying Jackal packages.
     5  package packager
     6  
     7  import (
     8  	"fmt"
     9  	"os"
    10  	"path/filepath"
    11  
    12  	"github.com/AlecAivazis/survey/v2"
    13  	"github.com/Racer159/jackal/src/config"
    14  	"github.com/Racer159/jackal/src/pkg/layout"
    15  	"github.com/Racer159/jackal/src/pkg/message"
    16  	"github.com/Racer159/jackal/src/pkg/utils"
    17  	"github.com/pterm/pterm"
    18  )
    19  
    20  func (p *Packager) confirmAction(stage string) (confirm bool) {
    21  
    22  	pterm.Println()
    23  	message.HeaderInfof("📦 PACKAGE DEFINITION")
    24  	utils.ColorPrintYAML(p.cfg.Pkg, p.getPackageYAMLHints(stage), true)
    25  
    26  	// Print any potential breaking changes (if this is a Deploy confirm) between this CLI version and the deployed init package
    27  	if stage == config.JackalDeployStage {
    28  		if p.cfg.Pkg.IsSBOMAble() {
    29  			// Print the location that the user can view the package SBOMs from
    30  			message.HorizontalRule()
    31  			message.Title("Software Bill of Materials", "an inventory of all software contained in this package")
    32  
    33  			if len(p.sbomViewFiles) > 0 {
    34  				cwd, _ := os.Getwd()
    35  				link := pterm.FgLightCyan.Sprint(pterm.Bold.Sprint(filepath.Join(cwd, layout.SBOMDir, filepath.Base(p.sbomViewFiles[0]))))
    36  				inspect := pterm.BgBlack.Sprint(pterm.FgWhite.Sprint(pterm.Bold.Sprintf("$ jackal package inspect %s", p.cfg.PkgOpts.PackageSource)))
    37  
    38  				artifactMsg := pterm.Bold.Sprintf("%d artifacts", len(p.sbomViewFiles)) + " to be reviewed. These are"
    39  				if len(p.sbomViewFiles) == 1 {
    40  					artifactMsg = pterm.Bold.Sprintf("%d artifact", len(p.sbomViewFiles)) + " to be reviewed. This is"
    41  				}
    42  
    43  				msg := fmt.Sprintf("This package has %s available in a temporary '%s' folder in this directory and will be removed upon deployment.\n", artifactMsg, pterm.Bold.Sprint("jackal-sbom"))
    44  				viewNow := fmt.Sprintf("\n- View SBOMs %s by navigating to the '%s' folder or copying this link into a browser:\n%s", pterm.Bold.Sprint("now"), pterm.Bold.Sprint("jackal-sbom"), link)
    45  				viewLater := fmt.Sprintf("\n- View SBOMs %s deployment with this command:\n%s", pterm.Bold.Sprint("after"), inspect)
    46  
    47  				message.Note(msg)
    48  				pterm.Println(viewNow)
    49  				pterm.Println(viewLater)
    50  			} else {
    51  				message.Warn("This package does NOT contain an SBOM.  If you require an SBOM, please contact the creator of this package to request a version that includes an SBOM.")
    52  			}
    53  		}
    54  	}
    55  
    56  	if len(p.warnings) > 0 {
    57  		message.HorizontalRule()
    58  		message.Title("Package Warnings", "the following warnings were flagged while reading the package")
    59  		for _, warning := range p.warnings {
    60  			message.Warn(warning)
    61  		}
    62  	}
    63  
    64  	message.HorizontalRule()
    65  
    66  	// Display prompt if not auto-confirmed
    67  	if config.CommonOptions.Confirm {
    68  		pterm.Println()
    69  		message.Successf("%s Jackal package confirmed", stage)
    70  		return config.CommonOptions.Confirm
    71  	}
    72  
    73  	prompt := &survey.Confirm{
    74  		Message: stage + " this Jackal package?",
    75  	}
    76  
    77  	pterm.Println()
    78  
    79  	// Prompt the user for confirmation, on abort return false
    80  	if err := survey.AskOne(prompt, &confirm); err != nil || !confirm {
    81  		// User aborted or declined, cancel the action
    82  		return false
    83  	}
    84  
    85  	return true
    86  }
    87  
    88  func (p *Packager) getPackageYAMLHints(stage string) map[string]string {
    89  	hints := map[string]string{}
    90  
    91  	if stage == config.JackalDeployStage {
    92  		for _, variable := range p.cfg.Pkg.Variables {
    93  			value, present := p.cfg.PkgOpts.SetVariables[variable.Name]
    94  			if !present {
    95  				value = fmt.Sprintf("'%s' (default)", message.Truncate(variable.Default, 20, false))
    96  			} else {
    97  				value = fmt.Sprintf("'%s'", message.Truncate(value, 20, false))
    98  			}
    99  			if variable.Sensitive {
   100  				value = "'**sanitized**'"
   101  			}
   102  			hints = utils.AddRootListHint(hints, "name", variable.Name, fmt.Sprintf("currently set to %s", value))
   103  		}
   104  	}
   105  
   106  	hints = utils.AddRootHint(hints, "metadata", "information about this package\n")
   107  	hints = utils.AddRootHint(hints, "build", "info about the machine, jackal version, and user that created this package\n")
   108  	hints = utils.AddRootHint(hints, "components", "components selected for this operation")
   109  	hints = utils.AddRootHint(hints, "constants", "static values set by the package author")
   110  	hints = utils.AddRootHint(hints, "variables", "deployment-specific values that are set on each package deployment")
   111  
   112  	return hints
   113  }