mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-01-11 23:49:30 -05:00
consistently use stdout and stderr (#502)
* consistently use stdout and stderr Signed-off-by: Fabian Kammel <fk@edgeless.systems>
This commit is contained in:
parent
e011c7ef78
commit
81a5907f26
@ -29,11 +29,11 @@ type Upgrader struct {
|
|||||||
measurementsUpdater measurementsUpdater
|
measurementsUpdater measurementsUpdater
|
||||||
imageUpdater imageUpdater
|
imageUpdater imageUpdater
|
||||||
|
|
||||||
writer io.Writer
|
outWriter io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUpgrader returns a new Upgrader.
|
// NewUpgrader returns a new Upgrader.
|
||||||
func NewUpgrader(writer io.Writer) (*Upgrader, error) {
|
func NewUpgrader(outWriter io.Writer) (*Upgrader, error) {
|
||||||
kubeConfig, err := clientcmd.BuildConfigFromFlags("", constants.AdminConfFilename)
|
kubeConfig, err := clientcmd.BuildConfigFromFlags("", constants.AdminConfFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("building kubernetes config: %w", err)
|
return nil, fmt.Errorf("building kubernetes config: %w", err)
|
||||||
@ -53,7 +53,7 @@ func NewUpgrader(writer io.Writer) (*Upgrader, error) {
|
|||||||
return &Upgrader{
|
return &Upgrader{
|
||||||
measurementsUpdater: &kubeMeasurementsUpdater{client: kubeClient},
|
measurementsUpdater: &kubeMeasurementsUpdater{client: kubeClient},
|
||||||
imageUpdater: &kubeImageUpdater{client: unstructuredClient},
|
imageUpdater: &kubeImageUpdater{client: unstructuredClient},
|
||||||
writer: writer,
|
outWriter: outWriter,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ func (u *Upgrader) updateMeasurements(ctx context.Context, measurements map[uint
|
|||||||
}
|
}
|
||||||
if !changed {
|
if !changed {
|
||||||
// measurements are the same, nothing to be done
|
// measurements are the same, nothing to be done
|
||||||
fmt.Fprintln(u.writer, "Cluster is already using the chosen measurements, skipping measurements upgrade")
|
fmt.Fprintln(u.outWriter, "Cluster is already using the chosen measurements, skipping measurements upgrade")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,7 +136,7 @@ func (u *Upgrader) updateMeasurements(ctx context.Context, measurements map[uint
|
|||||||
return fmt.Errorf("setting new measurements: %w", err)
|
return fmt.Errorf("setting new measurements: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintln(u.writer, "Successfully updated the cluster's expected measurements")
|
fmt.Fprintln(u.outWriter, "Successfully updated the cluster's expected measurements")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ func (u *Upgrader) updateImage(ctx context.Context, image string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if currentImageDefinition == image {
|
if currentImageDefinition == image {
|
||||||
fmt.Fprintln(u.writer, "Cluster is already using the chosen image, skipping image upgrade")
|
fmt.Fprintln(u.outWriter, "Cluster is already using the chosen image, skipping image upgrade")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +156,7 @@ func (u *Upgrader) updateImage(ctx context.Context, image string) error {
|
|||||||
return fmt.Errorf("setting new image: %w", err)
|
return fmt.Errorf("setting new image: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintln(u.writer, "Successfully updated the cluster's image, upgrades will be applied automatically")
|
fmt.Fprintln(u.outWriter, "Successfully updated the cluster's image, upgrades will be applied automatically")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ func TestUpdateMeasurements(t *testing.T) {
|
|||||||
|
|
||||||
upgrader := &Upgrader{
|
upgrader := &Upgrader{
|
||||||
measurementsUpdater: tc.updater,
|
measurementsUpdater: tc.updater,
|
||||||
writer: &bytes.Buffer{},
|
outWriter: &bytes.Buffer{},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := upgrader.updateMeasurements(context.Background(), tc.newMeasurements)
|
err := upgrader.updateMeasurements(context.Background(), tc.newMeasurements)
|
||||||
@ -203,7 +203,7 @@ func TestUpdateImage(t *testing.T) {
|
|||||||
|
|
||||||
upgrader := &Upgrader{
|
upgrader := &Upgrader{
|
||||||
imageUpdater: tc.updater,
|
imageUpdater: tc.updater,
|
||||||
writer: &bytes.Buffer{},
|
outWriter: &bytes.Buffer{},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := upgrader.updateImage(context.Background(), tc.newImage)
|
err := upgrader.updateImage(context.Background(), tc.newImage)
|
||||||
|
@ -63,7 +63,7 @@ func configFetchMeasurements(cmd *cobra.Command, verifier rekorVerifier, fileHan
|
|||||||
}
|
}
|
||||||
|
|
||||||
if conf.IsDebugImage() {
|
if conf.IsDebugImage() {
|
||||||
cmd.Println("Configured image doesn't look like a released production image. Double check image before deploying to production.")
|
cmd.PrintErrln("Configured image doesn't look like a released production image. Double check image before deploying to production.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := flags.updateURLs(conf); err != nil {
|
if err := flags.updateURLs(conf); err != nil {
|
||||||
@ -79,8 +79,8 @@ func configFetchMeasurements(cmd *cobra.Command, verifier rekorVerifier, fileHan
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := verifyWithRekor(cmd.Context(), verifier, hash); err != nil {
|
if err := verifyWithRekor(cmd.Context(), verifier, hash); err != nil {
|
||||||
cmd.Printf("Ignoring Rekor related error: %v\n", err)
|
cmd.PrintErrf("Ignoring Rekor related error: %v\n", err)
|
||||||
cmd.Println("Make sure the downloaded measurements are trustworthy!")
|
cmd.PrintErrln("Make sure the downloaded measurements are trustworthy!")
|
||||||
}
|
}
|
||||||
|
|
||||||
conf.UpdateMeasurements(fetchedMeasurements)
|
conf.UpdateMeasurements(fetchedMeasurements)
|
||||||
|
@ -7,7 +7,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/config/instancetypes"
|
"github.com/edgelesssys/constellation/v2/internal/config/instancetypes"
|
||||||
@ -27,7 +26,7 @@ func newConfigInstanceTypesCmd() *cobra.Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func printSupportedInstanceTypes(cmd *cobra.Command, args []string) {
|
func printSupportedInstanceTypes(cmd *cobra.Command, args []string) {
|
||||||
fmt.Printf(`AWS instance families:
|
cmd.Printf(`AWS instance families:
|
||||||
%v
|
%v
|
||||||
Azure Confidential VM instance types:
|
Azure Confidential VM instance types:
|
||||||
%v
|
%v
|
||||||
|
@ -41,7 +41,7 @@ func NewCreateCmd() *cobra.Command {
|
|||||||
|
|
||||||
func runCreate(cmd *cobra.Command, args []string) error {
|
func runCreate(cmd *cobra.Command, args []string) error {
|
||||||
fileHandler := file.NewHandler(afero.NewOsFs())
|
fileHandler := file.NewHandler(afero.NewOsFs())
|
||||||
spinner := newSpinner(cmd.OutOrStdout())
|
spinner := newSpinner(cmd.ErrOrStderr())
|
||||||
defer spinner.Stop()
|
defer spinner.Stop()
|
||||||
creator := cloudcmd.NewCreator(spinner)
|
creator := cloudcmd.NewCreator(spinner)
|
||||||
|
|
||||||
@ -59,34 +59,34 @@ func create(cmd *cobra.Command, creator cloudCreator, fileHandler file.Handler,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err := readConfig(cmd.OutOrStdout(), fileHandler, flags.configPath)
|
config, err := readConfig(cmd.ErrOrStderr(), fileHandler, flags.configPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("reading and validating config: %w", err)
|
return fmt.Errorf("reading and validating config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var printedAWarning bool
|
var printedAWarning bool
|
||||||
if config.IsDebugImage() {
|
if config.IsDebugImage() {
|
||||||
cmd.Println("Configured image doesn't look like a released production image. Double check image before deploying to production.")
|
cmd.PrintErrln("Configured image doesn't look like a released production image. Double check image before deploying to production.")
|
||||||
printedAWarning = true
|
printedAWarning = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.IsDebugCluster() {
|
if config.IsDebugCluster() {
|
||||||
cmd.Println("WARNING: Creating a debug cluster. This cluster is not secure and should only be used for debugging purposes.")
|
cmd.PrintErrln("WARNING: Creating a debug cluster. This cluster is not secure and should only be used for debugging purposes.")
|
||||||
cmd.Println("DO NOT USE THIS CLUSTER IN PRODUCTION.")
|
cmd.PrintErrln("DO NOT USE THIS CLUSTER IN PRODUCTION.")
|
||||||
printedAWarning = true
|
printedAWarning = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.IsAzureNonCVM() {
|
if config.IsAzureNonCVM() {
|
||||||
cmd.Println("Disabling Confidential VMs is insecure. Use only for evaluation purposes.")
|
cmd.PrintErrln("Disabling Confidential VMs is insecure. Use only for evaluation purposes.")
|
||||||
printedAWarning = true
|
printedAWarning = true
|
||||||
if config.EnforcesIDKeyDigest() {
|
if config.EnforcesIDKeyDigest() {
|
||||||
cmd.Println("Your config asks for enforcing the idkeydigest. This is only available on Confidential VMs. It will not be enforced.")
|
cmd.PrintErrln("Your config asks for enforcing the idkeydigest. This is only available on Confidential VMs. It will not be enforced.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print an extra new line later to separate warnings from the prompt message of the create command
|
// Print an extra new line later to separate warnings from the prompt message of the create command
|
||||||
if printedAWarning {
|
if printedAWarning {
|
||||||
cmd.Println("")
|
cmd.PrintErrln("")
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := config.GetProvider()
|
provider := config.GetProvider()
|
||||||
|
@ -79,7 +79,7 @@ func initialize(cmd *cobra.Command, newDialer func(validator *cloudcmd.Validator
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err := readConfig(cmd.OutOrStdout(), fileHandler, flags.configPath)
|
config, err := readConfig(cmd.ErrOrStderr(), fileHandler, flags.configPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("reading and validating config: %w", err)
|
return fmt.Errorf("reading and validating config: %w", err)
|
||||||
}
|
}
|
||||||
@ -94,13 +94,13 @@ func initialize(cmd *cobra.Command, newDialer func(validator *cloudcmd.Validator
|
|||||||
return fmt.Errorf("validating kubernetes version: %w", err)
|
return fmt.Errorf("validating kubernetes version: %w", err)
|
||||||
}
|
}
|
||||||
if versions.IsPreviewK8sVersion(k8sVersion) {
|
if versions.IsPreviewK8sVersion(k8sVersion) {
|
||||||
cmd.Printf("Warning: Constellation with Kubernetes %v is still in preview. Use only for evaluation purposes.\n", k8sVersion)
|
cmd.PrintErrf("Warning: Constellation with Kubernetes %v is still in preview. Use only for evaluation purposes.\n", k8sVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := config.GetProvider()
|
provider := config.GetProvider()
|
||||||
checker := license.NewChecker(quotaChecker, fileHandler)
|
checker := license.NewChecker(quotaChecker, fileHandler)
|
||||||
if err := checker.CheckLicense(cmd.Context(), provider, config.Provider, cmd.Printf); err != nil {
|
if err := checker.CheckLicense(cmd.Context(), provider, config.Provider, cmd.Printf); err != nil {
|
||||||
cmd.Printf("License check failed: %v", err)
|
cmd.PrintErrf("License check failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var sshUsers []*ssh.UserKey
|
var sshUsers []*ssh.UserKey
|
||||||
@ -290,7 +290,7 @@ type masterSecret struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// readOrGenerateMasterSecret reads a base64 encoded master secret from file or generates a new 32 byte secret.
|
// readOrGenerateMasterSecret reads a base64 encoded master secret from file or generates a new 32 byte secret.
|
||||||
func readOrGenerateMasterSecret(writer io.Writer, fileHandler file.Handler, filename string) (masterSecret, error) {
|
func readOrGenerateMasterSecret(outWriter io.Writer, fileHandler file.Handler, filename string) (masterSecret, error) {
|
||||||
if filename != "" {
|
if filename != "" {
|
||||||
var secret masterSecret
|
var secret masterSecret
|
||||||
if err := fileHandler.ReadJSON(filename, &secret); err != nil {
|
if err := fileHandler.ReadJSON(filename, &secret); err != nil {
|
||||||
@ -323,7 +323,7 @@ func readOrGenerateMasterSecret(writer io.Writer, fileHandler file.Handler, file
|
|||||||
if err := fileHandler.WriteJSON(constants.MasterSecretFilename, secret, file.OptNone); err != nil {
|
if err := fileHandler.WriteJSON(constants.MasterSecretFilename, secret, file.OptNone); err != nil {
|
||||||
return masterSecret{}, err
|
return masterSecret{}, err
|
||||||
}
|
}
|
||||||
fmt.Fprintf(writer, "Your Constellation master secret was successfully written to ./%s\n", constants.MasterSecretFilename)
|
fmt.Fprintf(outWriter, "Your Constellation master secret was successfully written to ./%s\n", constants.MasterSecretFilename)
|
||||||
return secret, nil
|
return secret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ func newMiniUpCmd() *cobra.Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runUp(cmd *cobra.Command, args []string) error {
|
func runUp(cmd *cobra.Command, args []string) error {
|
||||||
spinner := newSpinner(cmd.OutOrStdout())
|
spinner := newSpinner(cmd.ErrOrStderr())
|
||||||
defer spinner.Stop()
|
defer spinner.Stop()
|
||||||
creator := cloudcmd.NewCreator(spinner)
|
creator := cloudcmd.NewCreator(spinner)
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ func runUp(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func up(cmd *cobra.Command, creator cloudCreator, spinner spinnerInterf) error {
|
func up(cmd *cobra.Command, creator cloudCreator, spinner spinnerInterf) error {
|
||||||
if err := checkSystemRequirements(cmd.OutOrStdout()); err != nil {
|
if err := checkSystemRequirements(cmd.ErrOrStderr()); err != nil {
|
||||||
return fmt.Errorf("system requirements not met: %w", err)
|
return fmt.Errorf("system requirements not met: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,7 +163,7 @@ func prepareConfig(cmd *cobra.Command, fileHandler file.Handler) (*config.Config
|
|||||||
|
|
||||||
// check for existing config
|
// check for existing config
|
||||||
if configPath != "" {
|
if configPath != "" {
|
||||||
config, err := readConfig(cmd.OutOrStdout(), fileHandler, configPath)
|
config, err := readConfig(cmd.ErrOrStderr(), fileHandler, configPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -178,7 +178,7 @@ func prepareConfig(cmd *cobra.Command, fileHandler file.Handler) (*config.Config
|
|||||||
_, err = fileHandler.Stat(constants.ConfigFilename)
|
_, err = fileHandler.Stat(constants.ConfigFilename)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// config already exists, prompt user to overwrite
|
// config already exists, prompt user to overwrite
|
||||||
cmd.Println("A config file already exists in the current workspace.")
|
cmd.PrintErrln("A config file already exists in the current workspace.")
|
||||||
ok, err := askToConfirm(cmd, "Do you want to overwrite it?")
|
ok, err := askToConfirm(cmd, "Do you want to overwrite it?")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -194,7 +194,7 @@ func prepareConfig(cmd *cobra.Command, fileHandler file.Handler) (*config.Config
|
|||||||
cmd.Printf("Using existing image at %s\n\n", imagePath)
|
cmd.Printf("Using existing image at %s\n\n", imagePath)
|
||||||
} else if errors.Is(err, os.ErrNotExist) {
|
} else if errors.Is(err, os.ErrNotExist) {
|
||||||
cmd.Printf("Downloading image to %s\n", imagePath)
|
cmd.Printf("Downloading image to %s\n", imagePath)
|
||||||
if err := installImage(cmd.Context(), cmd.OutOrStdout(), versions.ConstellationQEMUImageURL, imagePath); err != nil {
|
if err := installImage(cmd.Context(), cmd.ErrOrStderr(), versions.ConstellationQEMUImageURL, imagePath); err != nil {
|
||||||
return nil, fmt.Errorf("downloading image to %s: %w", imagePath, err)
|
return nil, fmt.Errorf("downloading image to %s: %w", imagePath, err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -226,10 +226,10 @@ func initializeMiniCluster(cmd *cobra.Command, fileHandler file.Handler, spinner
|
|||||||
// clean up cluster resources if initialization fails
|
// clean up cluster resources if initialization fails
|
||||||
defer func() {
|
defer func() {
|
||||||
if retErr != nil {
|
if retErr != nil {
|
||||||
cmd.Printf("An error occurred: %s\n", retErr)
|
cmd.PrintErrf("An error occurred: %s\n", retErr)
|
||||||
cmd.Println("Attempting to roll back.")
|
cmd.PrintErrln("Attempting to roll back.")
|
||||||
_ = runDown(cmd, []string{})
|
_ = runDown(cmd, []string{})
|
||||||
cmd.Printf("Rollback succeeded.\n\n")
|
cmd.PrintErrf("Rollback succeeded.\n\n")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
newDialer := func(validator *cloudcmd.Validator) *dialer.Dialer {
|
newDialer := func(validator *cloudcmd.Validator) *dialer.Dialer {
|
||||||
@ -247,7 +247,7 @@ func initializeMiniCluster(cmd *cobra.Command, fileHandler file.Handler, spinner
|
|||||||
}
|
}
|
||||||
|
|
||||||
// installImage downloads the image from sourceURL to the destination.
|
// installImage downloads the image from sourceURL to the destination.
|
||||||
func installImage(ctx context.Context, out io.Writer, sourceURL, destination string) error {
|
func installImage(ctx context.Context, errWriter io.Writer, sourceURL, destination string) error {
|
||||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, sourceURL, nil)
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, sourceURL, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating request: %w", err)
|
return fmt.Errorf("creating request: %w", err)
|
||||||
@ -270,7 +270,7 @@ func installImage(ctx context.Context, out io.Writer, sourceURL, destination str
|
|||||||
|
|
||||||
bar := progressbar.NewOptions64(
|
bar := progressbar.NewOptions64(
|
||||||
resp.ContentLength,
|
resp.ContentLength,
|
||||||
progressbar.OptionSetWriter(out),
|
progressbar.OptionSetWriter(errWriter),
|
||||||
progressbar.OptionShowBytes(true),
|
progressbar.OptionShowBytes(true),
|
||||||
progressbar.OptionSetPredictTime(true),
|
progressbar.OptionSetPredictTime(true),
|
||||||
progressbar.OptionFullWidth(),
|
progressbar.OptionFullWidth(),
|
||||||
@ -282,7 +282,7 @@ func installImage(ctx context.Context, out io.Writer, sourceURL, destination str
|
|||||||
BarEnd: "]",
|
BarEnd: "]",
|
||||||
}),
|
}),
|
||||||
progressbar.OptionClearOnFinish(),
|
progressbar.OptionClearOnFinish(),
|
||||||
progressbar.OptionOnCompletion(func() { fmt.Fprintf(out, "Done.\n\n") }),
|
progressbar.OptionOnCompletion(func() { fmt.Fprintf(errWriter, "Done.\n\n") }),
|
||||||
)
|
)
|
||||||
defer bar.Close()
|
defer bar.Close()
|
||||||
|
|
||||||
|
@ -15,30 +15,30 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/v2/internal/file"
|
"github.com/edgelesssys/constellation/v2/internal/file"
|
||||||
)
|
)
|
||||||
|
|
||||||
func readConfig(out io.Writer, fileHandler file.Handler, name string) (*config.Config, error) {
|
func readConfig(errWriter io.Writer, fileHandler file.Handler, name string) (*config.Config, error) {
|
||||||
cnf, err := config.FromFile(fileHandler, name)
|
cnf, err := config.FromFile(fileHandler, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := validateConfig(out, cnf); err != nil {
|
if err := validateConfig(errWriter, cnf); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return cnf, nil
|
return cnf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateConfig(out io.Writer, cnf *config.Config) error {
|
func validateConfig(errWriter io.Writer, cnf *config.Config) error {
|
||||||
msgs, err := cnf.Validate()
|
msgs, err := cnf.Validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("performing config validation: %w", err)
|
return fmt.Errorf("performing config validation: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(msgs) > 0 {
|
if len(msgs) > 0 {
|
||||||
fmt.Fprintln(out, "Invalid fields in config file:")
|
fmt.Fprintln(errWriter, "Invalid fields in config file:")
|
||||||
for _, m := range msgs {
|
for _, m := range msgs {
|
||||||
fmt.Fprintln(out, "\t"+m)
|
fmt.Fprintln(errWriter, "\t"+m)
|
||||||
}
|
}
|
||||||
fmt.Fprintln(out, "Fix the invalid entries or generate a new configuration using `constellation config generate`")
|
fmt.Fprintln(errWriter, "Fix the invalid entries or generate a new configuration using `constellation config generate`")
|
||||||
return errors.New("invalid configuration")
|
return errors.New("invalid configuration")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ func recover(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err := readConfig(cmd.OutOrStdout(), fileHandler, flags.configPath)
|
config, err := readConfig(cmd.ErrOrStderr(), fileHandler, flags.configPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("reading and validating config: %w", err)
|
return fmt.Errorf("reading and validating config: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ func NewTerminateCmd() *cobra.Command {
|
|||||||
// runTerminate runs the terminate command.
|
// runTerminate runs the terminate command.
|
||||||
func runTerminate(cmd *cobra.Command, args []string) error {
|
func runTerminate(cmd *cobra.Command, args []string) error {
|
||||||
fileHandler := file.NewHandler(afero.NewOsFs())
|
fileHandler := file.NewHandler(afero.NewOsFs())
|
||||||
spinner := newSpinner(cmd.OutOrStdout())
|
spinner := newSpinner(cmd.ErrOrStderr())
|
||||||
defer spinner.Stop()
|
defer spinner.Stop()
|
||||||
terminator := cloudcmd.NewTerminator()
|
terminator := cloudcmd.NewTerminator()
|
||||||
|
|
||||||
|
@ -93,18 +93,18 @@ func upgradePlan(cmd *cobra.Command, planner upgradePlanner,
|
|||||||
}
|
}
|
||||||
compatibleImages := getCompatibleImages(csp, version, images)
|
compatibleImages := getCompatibleImages(csp, version, images)
|
||||||
if len(compatibleImages) == 0 {
|
if len(compatibleImages) == 0 {
|
||||||
cmd.Println("No compatible images found to upgrade to.")
|
cmd.PrintErrln("No compatible images found to upgrade to.")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// get expected measurements for each image
|
// get expected measurements for each image
|
||||||
if err := getCompatibleImageMeasurements(cmd.Context(), client, rekor, []byte(flags.cosignPubKey), compatibleImages); err != nil {
|
if err := getCompatibleImageMeasurements(cmd.Context(), cmd, client, rekor, []byte(flags.cosignPubKey), compatibleImages); err != nil {
|
||||||
return fmt.Errorf("fetching measurements for compatible images: %w", err)
|
return fmt.Errorf("fetching measurements for compatible images: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// interactive mode
|
// interactive mode
|
||||||
if flags.filePath == "" {
|
if flags.filePath == "" {
|
||||||
fmt.Fprintf(cmd.OutOrStdout(), "Current version: %s\n", version)
|
cmd.Printf("Current version: %s\n", version)
|
||||||
return upgradePlanInteractive(
|
return upgradePlanInteractive(
|
||||||
&nopWriteCloser{cmd.OutOrStdout()},
|
&nopWriteCloser{cmd.OutOrStdout()},
|
||||||
io.NopCloser(cmd.InOrStdin()),
|
io.NopCloser(cmd.InOrStdin()),
|
||||||
@ -179,7 +179,7 @@ func getCompatibleImages(csp cloudprovider.Provider, currentVersion string, imag
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getCompatibleImageMeasurements retrieves the expected measurements for each image.
|
// getCompatibleImageMeasurements retrieves the expected measurements for each image.
|
||||||
func getCompatibleImageMeasurements(ctx context.Context, client *http.Client, rekor rekorVerifier, pubK []byte, images map[string]config.UpgradeConfig) error {
|
func getCompatibleImageMeasurements(ctx context.Context, cmd *cobra.Command, client *http.Client, rekor rekorVerifier, pubK []byte, images map[string]config.UpgradeConfig) error {
|
||||||
for idx, img := range images {
|
for idx, img := range images {
|
||||||
measurementsURL, err := url.Parse(constants.S3PublicBucket + strings.ToLower(img.Image) + "/measurements.yaml")
|
measurementsURL, err := url.Parse(constants.S3PublicBucket + strings.ToLower(img.Image) + "/measurements.yaml")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -197,8 +197,8 @@ func getCompatibleImageMeasurements(ctx context.Context, client *http.Client, re
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err = verifyWithRekor(ctx, rekor, hash); err != nil {
|
if err = verifyWithRekor(ctx, rekor, hash); err != nil {
|
||||||
fmt.Printf("Warning: Unable to verify '%s' in Rekor.\n", hash)
|
cmd.PrintErrf("Warning: Unable to verify '%s' in Rekor.\n", hash)
|
||||||
fmt.Printf("Make sure measurements are correct.\n")
|
cmd.PrintErrf("Make sure measurements are correct.\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
images[idx] = img
|
images[idx] = img
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/file"
|
"github.com/edgelesssys/constellation/v2/internal/file"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"golang.org/x/mod/semver"
|
"golang.org/x/mod/semver"
|
||||||
@ -271,7 +272,7 @@ func TestGetCompatibleImageMeasurements(t *testing.T) {
|
|||||||
|
|
||||||
pubK := []byte("-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUs5fDUIz9aiwrfr8BK4VjN7jE6sl\ngz7UuXsOin8+dB0SGrbNHy7TJToa2fAiIKPVLTOfvY75DqRAtffhO1fpBA==\n-----END PUBLIC KEY-----")
|
pubK := []byte("-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUs5fDUIz9aiwrfr8BK4VjN7jE6sl\ngz7UuXsOin8+dB0SGrbNHy7TJToa2fAiIKPVLTOfvY75DqRAtffhO1fpBA==\n-----END PUBLIC KEY-----")
|
||||||
|
|
||||||
err := getCompatibleImageMeasurements(context.Background(), client, singleUUIDVerifier(), pubK, testImages)
|
err := getCompatibleImageMeasurements(context.Background(), &cobra.Command{}, client, singleUUIDVerifier(), pubK, testImages)
|
||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
|
|
||||||
for _, image := range testImages {
|
for _, image := range testImages {
|
||||||
@ -456,8 +457,10 @@ func TestUpgradePlan(t *testing.T) {
|
|||||||
|
|
||||||
cmd := newUpgradePlanCmd()
|
cmd := newUpgradePlanCmd()
|
||||||
cmd.SetContext(context.Background())
|
cmd.SetContext(context.Background())
|
||||||
var out bytes.Buffer
|
var outTarget bytes.Buffer
|
||||||
cmd.SetOut(&out)
|
cmd.SetOut(&outTarget)
|
||||||
|
var errTarget bytes.Buffer
|
||||||
|
cmd.SetErr(&errTarget)
|
||||||
|
|
||||||
client := newTestClient(func(req *http.Request) *http.Response {
|
client := newTestClient(func(req *http.Request) *http.Response {
|
||||||
if req.URL.String() == imageReleaseURL {
|
if req.URL.String() == imageReleaseURL {
|
||||||
@ -497,13 +500,13 @@ func TestUpgradePlan(t *testing.T) {
|
|||||||
|
|
||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
if !tc.wantUpgrade {
|
if !tc.wantUpgrade {
|
||||||
assert.Contains(out.String(), "No compatible images")
|
assert.Contains(errTarget.String(), "No compatible images")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var availableUpgrades map[string]config.UpgradeConfig
|
var availableUpgrades map[string]config.UpgradeConfig
|
||||||
if tc.flags.filePath == "-" {
|
if tc.flags.filePath == "-" {
|
||||||
require.NoError(yaml.Unmarshal(out.Bytes(), &availableUpgrades))
|
require.NoError(yaml.Unmarshal(outTarget.Bytes(), &availableUpgrades))
|
||||||
} else {
|
} else {
|
||||||
require.NoError(fileHandler.ReadYAMLStrict(tc.flags.filePath, &availableUpgrades))
|
require.NoError(fileHandler.ReadYAMLStrict(tc.flags.filePath, &availableUpgrades))
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ func verify(cmd *cobra.Command, fileHandler file.Handler, verifyClient verifyCli
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err := readConfig(cmd.OutOrStdout(), fileHandler, flags.configPath)
|
config, err := readConfig(cmd.ErrOrStderr(), fileHandler, flags.configPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("reading and validating config: %w", err)
|
return fmt.Errorf("reading and validating config: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ func NewVersionCmd() *cobra.Command {
|
|||||||
func runVersion(cmd *cobra.Command, args []string) {
|
func runVersion(cmd *cobra.Command, args []string) {
|
||||||
buildInfo, ok := debug.ReadBuildInfo()
|
buildInfo, ok := debug.ReadBuildInfo()
|
||||||
if !ok {
|
if !ok {
|
||||||
cmd.Printf("Unable to retrieve build info. Is buildvcs enabled?")
|
cmd.PrintErrf("Unable to retrieve build info. Is buildvcs enabled?")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user