AB#2033 User-friendly wrap and reword errors

fix: readOrGenerated function signature
This commit is contained in:
Christoph Meyer 2022-06-09 14:10:42 +00:00 committed by cm
parent 9441e46e4b
commit 1e11188dac
10 changed files with 61 additions and 56 deletions

View File

@ -1,6 +1,8 @@
package cmd
import (
"fmt"
"github.com/edgelesssys/constellation/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/internal/config"
"github.com/edgelesssys/constellation/internal/constants"
@ -50,7 +52,7 @@ func configGenerate(cmd *cobra.Command, fileHandler file.Handler, provider cloud
if flags.file == "-" {
content, err := encoder.NewEncoder(conf).Encode()
if err != nil {
return err
return fmt.Errorf("encoding config content: %w", err)
}
_, err = cmd.OutOrStdout().Write(content)
return err
@ -62,7 +64,7 @@ func configGenerate(cmd *cobra.Command, fileHandler file.Handler, provider cloud
func parseGenerateFlags(cmd *cobra.Command) (generateFlags, error) {
file, err := cmd.Flags().GetString("file")
if err != nil {
return generateFlags{}, err
return generateFlags{}, fmt.Errorf("parsing config generate flags: %w", err)
}
return generateFlags{
file: file,

View File

@ -70,7 +70,7 @@ func create(cmd *cobra.Command, creator cloudCreator, fileHandler file.Handler,
config, err := readConfig(cmd.OutOrStdout(), fileHandler, flags.configPath, provider)
if err != nil {
return err
return fmt.Errorf("reading and validating config: %w", err)
}
if !flags.yes {
@ -105,7 +105,7 @@ func create(cmd *cobra.Command, creator cloudCreator, fileHandler file.Handler,
func parseCreateFlags(cmd *cobra.Command, provider cloudprovider.Provider) (createFlags, error) {
controllerCount, err := cmd.Flags().GetInt("control-plane-nodes")
if err != nil {
return createFlags{}, err
return createFlags{}, fmt.Errorf("parsing number of control-plane nodes: %w", err)
}
if controllerCount < constants.MinControllerCount {
return createFlags{}, fmt.Errorf("number of control-plane nodes must be at least %d", constants.MinControllerCount)
@ -113,7 +113,7 @@ func parseCreateFlags(cmd *cobra.Command, provider cloudprovider.Provider) (crea
workerCount, err := cmd.Flags().GetInt("worker-nodes")
if err != nil {
return createFlags{}, err
return createFlags{}, fmt.Errorf("parsing number of worker nodes: %w", err)
}
if workerCount < constants.MinWorkerCount {
return createFlags{}, fmt.Errorf("number of worker nodes must be at least %d", constants.MinWorkerCount)
@ -121,7 +121,7 @@ func parseCreateFlags(cmd *cobra.Command, provider cloudprovider.Provider) (crea
insType, err := cmd.Flags().GetString("instance-type")
if err != nil {
return createFlags{}, err
return createFlags{}, fmt.Errorf("parsing instance type argument: %w", err)
}
if insType == "" {
insType = defaultInstanceType(provider)
@ -132,7 +132,7 @@ func parseCreateFlags(cmd *cobra.Command, provider cloudprovider.Provider) (crea
name, err := cmd.Flags().GetString("name")
if err != nil {
return createFlags{}, err
return createFlags{}, fmt.Errorf("parsing name argument: %w", err)
}
if len(name) > constants.ConstellationNameLength {
return createFlags{}, fmt.Errorf(
@ -143,12 +143,12 @@ func parseCreateFlags(cmd *cobra.Command, provider cloudprovider.Provider) (crea
yes, err := cmd.Flags().GetBool("yes")
if err != nil {
return createFlags{}, err
return createFlags{}, fmt.Errorf("%w; Set '-yes' without a value to automatically confirm", err)
}
configPath, err := cmd.Flags().GetString("config")
if err != nil {
return createFlags{}, err
return createFlags{}, fmt.Errorf("parsing config path argument: %w", err)
}
return createFlags{
@ -192,7 +192,7 @@ func checkDirClean(fileHandler file.Handler) error {
return fmt.Errorf("file '%s' already exists in working directory, run 'constellation terminate' before creating a new one", constants.AdminConfFilename)
}
if _, err := fileHandler.Stat(constants.MasterSecretFilename); !errors.Is(err, fs.ErrNotExist) {
return fmt.Errorf("file '%s' already exists in working directory, clean it up first", constants.MasterSecretFilename)
return fmt.Errorf("file '%s' already exists in working directory. Constellation won't overwrite previous master secrets. Move it somewhere or delete it before creating a new cluster", constants.MasterSecretFilename)
}
return nil

View File

@ -80,16 +80,16 @@ func initialize(ctx context.Context, cmd *cobra.Command, protCl protoClient, ser
var stat state.ConstellationState
err = fileHandler.ReadJSON(constants.StateFilename, &stat)
if errors.Is(err, fs.ErrNotExist) {
return fmt.Errorf("nothing to initialize: %w", err)
return fmt.Errorf("missing Constellation state file: %w. Please do 'constellation create ...' before 'constellation init'", err)
} else if err != nil {
return err
return fmt.Errorf("loading Constellation state file: %w", err)
}
provider := cloudprovider.FromString(stat.CloudProvider)
config, err := readConfig(cmd.OutOrStdout(), fileHandler, flags.configPath, provider)
if err != nil {
return err
return fmt.Errorf("reading and validating config: %w", err)
}
var sshUsers []*ssh.UserKey
@ -166,7 +166,7 @@ func initialize(ctx context.Context, cmd *cobra.Command, protCl protoClient, ser
if flags.autoconfigureWG {
if err := vpnHandler.Apply(vpnConfig); err != nil {
return err
return fmt.Errorf("configuring WireGuard: %w", err)
}
}
@ -247,7 +247,7 @@ type activationResult struct {
func writeWGQuickFile(fileHandler file.Handler, vpnHandler vpnHandler, vpnConfig *wgquick.Config) error {
data, err := vpnHandler.Marshal(vpnConfig)
if err != nil {
return err
return fmt.Errorf("marshalling VPN config: %w", err)
}
return fileHandler.Write(constants.WGQuickConfigFilename, data, file.OptNone)
}
@ -285,7 +285,7 @@ func writeRow(wr io.Writer, col1 string, col2 string) {
func evalFlagArgs(cmd *cobra.Command, fileHandler file.Handler) (initFlags, error) {
userPrivKeyPath, err := cmd.Flags().GetString("privatekey")
if err != nil {
return initFlags{}, err
return initFlags{}, fmt.Errorf("parsing privatekey path argument: %w", err)
}
userPrivKey, userPubKey, err := readOrGenerateVPNKey(fileHandler, userPrivKeyPath)
if err != nil {
@ -293,23 +293,23 @@ func evalFlagArgs(cmd *cobra.Command, fileHandler file.Handler) (initFlags, erro
}
autoconfigureWG, err := cmd.Flags().GetBool("wg-autoconfig")
if err != nil {
return initFlags{}, err
return initFlags{}, fmt.Errorf("parsing wg-autoconfig argument: %w", err)
}
masterSecretPath, err := cmd.Flags().GetString("master-secret")
if err != nil {
return initFlags{}, err
return initFlags{}, fmt.Errorf("parsing master-secret path argument: %w", err)
}
masterSecret, err := readOrGeneratedMasterSecret(cmd.OutOrStdout(), fileHandler, masterSecretPath)
masterSecret, err := readOrGenerateMasterSecret(cmd.OutOrStdout(), fileHandler, masterSecretPath)
if err != nil {
return initFlags{}, err
return initFlags{}, fmt.Errorf("parsing or generating master mastersecret from file %s: %w", masterSecretPath, err)
}
autoscale, err := cmd.Flags().GetBool("autoscale")
if err != nil {
return initFlags{}, err
return initFlags{}, fmt.Errorf("parsing autoscale argument: %w", err)
}
configPath, err := cmd.Flags().GetString("config")
if err != nil {
return initFlags{}, err
return initFlags{}, fmt.Errorf("parsing config path argument: %w", err)
}
return initFlags{
@ -337,17 +337,17 @@ func readOrGenerateVPNKey(fileHandler file.Handler, privKeyPath string) (privKey
if privKeyPath == "" {
privKeyParsed, err = wgtypes.GeneratePrivateKey()
if err != nil {
return nil, nil, err
return nil, nil, fmt.Errorf("generating WireGuard private key: %w", err)
}
privKey = []byte(privKeyParsed.String())
} else {
privKey, err = fileHandler.Read(privKeyPath)
if err != nil {
return nil, nil, err
return nil, nil, fmt.Errorf("reading the VPN private key: %w", err)
}
privKeyParsed, err = wgtypes.ParseKey(string(privKey))
if err != nil {
return nil, nil, err
return nil, nil, fmt.Errorf("parsing the WireGuard private key: %w", err)
}
}
@ -367,8 +367,8 @@ func ipsToEndpoints(ips []string, port string) []string {
return endpoints
}
// readOrGeneratedMasterSecret reads a base64 encoded master secret from file or generates a new 32 byte secret.
func readOrGeneratedMasterSecret(w io.Writer, fileHandler file.Handler, filename string) ([]byte, error) {
// 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) ([]byte, error) {
if filename != "" {
// Try to read the base64 secret from file
encodedSecret, err := fileHandler.Read(filename)
@ -393,7 +393,7 @@ func readOrGeneratedMasterSecret(w io.Writer, fileHandler file.Handler, filename
if err := fileHandler.Write(constants.MasterSecretFilename, []byte(base64.StdEncoding.EncodeToString(masterSecret)), file.OptNone); err != nil {
return nil, err
}
fmt.Fprintf(w, "Your Constellation master secret was successfully written to ./%s\n", constants.MasterSecretFilename)
fmt.Fprintf(writer, "Your Constellation master secret was successfully written to ./%s\n", constants.MasterSecretFilename)
return masterSecret, nil
}

View File

@ -414,7 +414,7 @@ func TestReadOrGenerateVPNKey(t *testing.T) {
assert.NotEmpty(pubK)
}
func TestReadOrGeneratedMasterSecret(t *testing.T) {
func TestReadOrGenerateMasterSecret(t *testing.T) {
testCases := map[string]struct {
filename string
filecontent string
@ -484,7 +484,7 @@ func TestReadOrGeneratedMasterSecret(t *testing.T) {
}
var out bytes.Buffer
secret, err := readOrGeneratedMasterSecret(&out, fileHandler, tc.filename)
secret, err := readOrGenerateMasterSecret(&out, fileHandler, tc.filename)
if tc.wantErr {
assert.Error(err)

View File

@ -24,7 +24,7 @@ func readConfig(out io.Writer, fileHandler file.Handler, name string, provider c
func validateConfig(out io.Writer, cnf *config.Config, provider cloudprovider.Provider) error {
msgs, err := cnf.Validate()
if err != nil {
return err
return fmt.Errorf("performing config validation: %w", err)
}
if len(msgs) > 0 {
@ -32,7 +32,7 @@ func validateConfig(out io.Writer, cnf *config.Config, provider cloudprovider.Pr
for _, m := range msgs {
fmt.Fprintln(out, "\t"+m)
}
return errors.New("invalid configuration")
return errors.New("invalid configuration. Fix the invalid entries or generate a new configuration using `constellation config generate`")
}
if provider != cloudprovider.Unknown && !cnf.HasProvider(provider) {

View File

@ -4,6 +4,7 @@ import (
"context"
"encoding/base64"
"errors"
"fmt"
"regexp"
"strings"
@ -60,7 +61,7 @@ func recover(ctx context.Context, cmd *cobra.Command, fileHandler file.Handler,
config, err := readConfig(cmd.OutOrStdout(), fileHandler, flags.configPath, provider)
if err != nil {
return err
return fmt.Errorf("reading and validating config: %w", err)
}
validators, err := cloudcmd.NewValidators(provider, config)
@ -89,16 +90,16 @@ func recover(ctx context.Context, cmd *cobra.Command, fileHandler file.Handler,
func parseRecoverFlags(cmd *cobra.Command, fileHandler file.Handler) (recoverFlags, error) {
endpoint, err := cmd.Flags().GetString("endpoint")
if err != nil {
return recoverFlags{}, err
return recoverFlags{}, fmt.Errorf("parsing endpoint argument: %w", err)
}
endpoint, err = validateEndpoint(endpoint, constants.CoordinatorPort)
if err != nil {
return recoverFlags{}, err
return recoverFlags{}, fmt.Errorf("validating endpoint argument: %w", err)
}
diskUUID, err := cmd.Flags().GetString("disk-uuid")
if err != nil {
return recoverFlags{}, err
return recoverFlags{}, fmt.Errorf("parsing disk-uuid argument: %w", err)
}
if match := diskUUIDRegexp.MatchString(diskUUID); !match {
return recoverFlags{}, errors.New("flag '--disk-uuid' isn't a valid LUKS UUID")
@ -107,16 +108,16 @@ func parseRecoverFlags(cmd *cobra.Command, fileHandler file.Handler) (recoverFla
masterSecretPath, err := cmd.Flags().GetString("master-secret")
if err != nil {
return recoverFlags{}, err
return recoverFlags{}, fmt.Errorf("parsing master-secret path argument: %w", err)
}
masterSecret, err := readMasterSecret(fileHandler, masterSecretPath)
if err != nil {
return recoverFlags{}, err
return recoverFlags{}, fmt.Errorf("reading the master secret from file %s: %w", masterSecretPath, err)
}
configPath, err := cmd.Flags().GetString("config")
if err != nil {
return recoverFlags{}, err
return recoverFlags{}, fmt.Errorf("parsing config path argument: %w", err)
}
return recoverFlags{

View File

@ -38,28 +38,28 @@ func runTerminate(cmd *cobra.Command, args []string) error {
func terminate(cmd *cobra.Command, terminator cloudTerminator, fileHandler file.Handler) error {
var stat state.ConstellationState
if err := fileHandler.ReadJSON(constants.StateFilename, &stat); err != nil {
return err
return fmt.Errorf("reading Constellation state: %w", err)
}
cmd.Println("Terminating ...")
if err := terminator.Terminate(cmd.Context(), stat); err != nil {
return err
return fmt.Errorf("terminating Constellation cluster: %w", err)
}
cmd.Println("Your Constellation cluster was terminated successfully.")
var retErr error
if err := fileHandler.Remove(constants.StateFilename); err != nil {
retErr = multierr.Append(err, fmt.Errorf("failed to remove file '%s', please remove manually", constants.StateFilename))
retErr = multierr.Append(err, fmt.Errorf("failed to remove file: '%s', please remove it manually", constants.StateFilename))
}
if err := fileHandler.Remove(constants.AdminConfFilename); err != nil && !errors.Is(err, fs.ErrNotExist) {
retErr = multierr.Append(err, fmt.Errorf("failed to remove file '%s', please remove manually", constants.AdminConfFilename))
retErr = multierr.Append(err, fmt.Errorf("failed to remove file: '%s', please remove it manually", constants.AdminConfFilename))
}
if err := fileHandler.Remove(constants.WGQuickConfigFilename); err != nil && !errors.Is(err, fs.ErrNotExist) {
retErr = multierr.Append(err, fmt.Errorf("failed to remove file '%s', please remove manually", constants.WGQuickConfigFilename))
retErr = multierr.Append(err, fmt.Errorf("failed to remove file: '%s', please remove it manually", constants.WGQuickConfigFilename))
}
return retErr

View File

@ -51,7 +51,7 @@ func verify(ctx context.Context, cmd *cobra.Command, provider cloudprovider.Prov
config, err := readConfig(cmd.OutOrStdout(), fileHandler, flags.configPath, provider)
if err != nil {
return err
return fmt.Errorf("reading and validating config: %w", err)
}
validators, err := cloudcmd.NewValidators(provider, config)
@ -83,28 +83,28 @@ func verify(ctx context.Context, cmd *cobra.Command, provider cloudprovider.Prov
func parseVerifyFlags(cmd *cobra.Command) (verifyFlags, error) {
ownerID, err := cmd.Flags().GetString("owner-id")
if err != nil {
return verifyFlags{}, err
return verifyFlags{}, fmt.Errorf("parsing owner-id argument: %w", err)
}
clusterID, err := cmd.Flags().GetString("unique-id")
if err != nil {
return verifyFlags{}, err
return verifyFlags{}, fmt.Errorf("parsing unique-id argument: %w", err)
}
if ownerID == "" && clusterID == "" {
return verifyFlags{}, errors.New("neither owner ID nor unique ID provided to verify the cluster")
return verifyFlags{}, errors.New("neither owner-id nor unique-id provided to verify the cluster")
}
endpoint, err := cmd.Flags().GetString("node-endpoint")
if err != nil {
return verifyFlags{}, err
return verifyFlags{}, fmt.Errorf("parsing node-endpoint argument: %w", err)
}
endpoint, err = validateEndpoint(endpoint, constants.CoordinatorPort)
if err != nil {
return verifyFlags{}, err
return verifyFlags{}, fmt.Errorf("validating endpoint argument: %w", err)
}
configPath, err := cmd.Flags().GetString("config")
if err != nil {
return verifyFlags{}, err
return verifyFlags{}, fmt.Errorf("parsing config path argument: %w", err)
}
return verifyFlags{

View File

@ -126,7 +126,7 @@ func (m *Metadata) GetInstance(ctx context.Context, providerID string) (cloudtyp
if scaleSetErr == nil {
return instance, nil
}
return cloudtypes.Instance{}, fmt.Errorf("retrieving instance given providerID %v as either single vm or scale set vm: %v; %v", providerID, singleErr, scaleSetErr)
return cloudtypes.Instance{}, fmt.Errorf("retrieving instance given providerID %v as either single VM or scale set VM: %v; %v", providerID, singleErr, scaleSetErr)
}
// SignalRole signals the constellation role via cloud provider metadata.

View File

@ -90,16 +90,18 @@ func (i *osInstaller) extractArchive(archivePath, prefix string, perm fs.FileMod
if len(header.Name) == 0 {
return errors.New("cannot create dir for empty path")
}
if err := i.fs.Mkdir(path.Join(prefix, header.Name), fs.FileMode(header.Mode)&perm); err != nil && !errors.Is(err, os.ErrExist) {
return fmt.Errorf("creating folder %s: %w", path.Join(prefix, header.Name), err)
prefixedPath := path.Join(prefix, header.Name)
if err := i.fs.Mkdir(prefixedPath, fs.FileMode(header.Mode)&perm); err != nil && !errors.Is(err, os.ErrExist) {
return fmt.Errorf("creating folder %q: %w", prefixedPath, err)
}
case tar.TypeReg:
if len(header.Name) == 0 {
return errors.New("cannot create file for empty path")
}
out, err := i.fs.OpenFile(path.Join(prefix, header.Name), os.O_WRONLY|os.O_CREATE, fs.FileMode(header.Mode))
prefixedPath := path.Join(prefix, header.Name)
out, err := i.fs.OpenFile(prefixedPath, os.O_WRONLY|os.O_CREATE, fs.FileMode(header.Mode))
if err != nil {
return fmt.Errorf("creating file %s for writing: %w", path.Join(prefix, header.Name), err)
return fmt.Errorf("creating file %q for writing: %w", prefixedPath, err)
}
defer out.Close()
if _, err := io.Copy(out, tarReader); err != nil {