feat: improve error handling.

- skip EOF error
This commit is contained in:
Fernandez Ludovic 2019-12-26 12:38:52 +01:00 committed by Ludovic Fernandez
parent 8c8f1ea37f
commit 1ef3d37498
7 changed files with 70 additions and 44 deletions

View File

@ -92,7 +92,7 @@ func createTLSConfig(cmd *cobra.Command) (*tls.Config, error) {
cert, err := getCertificate(privateKey, certContent) cert, err := getCertificate(privateKey, certContent)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to load TLS keypair: %s", err) return nil, fmt.Errorf("failed to load TLS keypair: %w", err)
} }
return &tls.Config{ return &tls.Config{
@ -109,7 +109,7 @@ func getCertPool(ca string) (*x509.CertPool, error) {
if ca != "" { if ca != "" {
caContent, err := getCAContent(ca) caContent, err := getCAContent(ca)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read CA. %s", err) return nil, fmt.Errorf("failed to read CA. %w", err)
} }
if !caPool.AppendCertsFromPEM(caContent) { if !caPool.AppendCertsFromPEM(caContent) {

View File

@ -109,7 +109,7 @@ func runE(apply func(*dumper.BaseConfig, *cobra.Command) error) func(*cobra.Comm
func tree(root, indent string) error { func tree(root, indent string) error {
fi, err := os.Stat(root) fi, err := os.Stat(root)
if err != nil { if err != nil {
return fmt.Errorf("could not stat %s: %v", root, err) return fmt.Errorf("could not stat %s: %w", root, err)
} }
fmt.Println(fi.Name()) fmt.Println(fi.Name())
@ -119,7 +119,7 @@ func tree(root, indent string) error {
fis, err := ioutil.ReadDir(root) fis, err := ioutil.ReadDir(root)
if err != nil { if err != nil {
return fmt.Errorf("could not read dir %s: %v", root, err) return fmt.Errorf("could not read dir %s: %w", root, err)
} }
var names []string var names []string

View File

@ -4,6 +4,8 @@ import (
"bytes" "bytes"
"crypto/md5" "crypto/md5"
"encoding/json" "encoding/json"
"errors"
"fmt"
"io" "io"
"log" "log"
"os" "os"
@ -34,20 +36,24 @@ func Dump(acmeFile string, baseConfig *dumper.BaseConfig) error {
func dump(acmeFile string, baseConfig *dumper.BaseConfig) error { func dump(acmeFile string, baseConfig *dumper.BaseConfig) error {
if baseConfig.Version == "v2" { if baseConfig.Version == "v2" {
return dumpV2(acmeFile, baseConfig) err := dumpV2(acmeFile, baseConfig)
if err != nil {
return fmt.Errorf("v2: dump failed: %w", err)
}
return nil
} }
return dumpV1(acmeFile, baseConfig) err := dumpV1(acmeFile, baseConfig)
if err != nil {
return fmt.Errorf("v1: dump failed: %w", err)
}
return nil
} }
func dumpV1(acmeFile string, baseConfig *dumper.BaseConfig) error { func dumpV1(acmeFile string, baseConfig *dumper.BaseConfig) error {
source, err := os.Open(acmeFile)
if err != nil {
return err
}
data := &v1.StoredData{} data := &v1.StoredData{}
if err = json.NewDecoder(source).Decode(data); err != nil { err := readJSONFile(acmeFile, data)
if err != nil {
return err return err
} }
@ -55,23 +61,38 @@ func dumpV1(acmeFile string, baseConfig *dumper.BaseConfig) error {
} }
func dumpV2(acmeFile string, baseConfig *dumper.BaseConfig) error { func dumpV2(acmeFile string, baseConfig *dumper.BaseConfig) error {
source, err := os.Open(acmeFile)
if err != nil {
return err
}
data := map[string]*acme.StoredData{} data := map[string]*acme.StoredData{}
if err = json.NewDecoder(source).Decode(&data); err != nil { err := readJSONFile(acmeFile, &data)
if err != nil {
return err return err
} }
return v2.Dump(data, baseConfig) return v2.Dump(data, baseConfig)
} }
func readJSONFile(acmeFile string, data interface{}) error {
source, err := os.Open(acmeFile)
if err != nil {
return fmt.Errorf("failed to open file %q: %w", acmeFile, err)
}
defer func() { _ = source.Close() }()
err = json.NewDecoder(source).Decode(data)
if errors.Is(err, io.EOF) {
log.Printf("warn: file %q may not be ready: %v", acmeFile, err)
return nil
}
if err != nil {
return fmt.Errorf("failed to unmarshal file %q: %w", acmeFile, err)
}
return nil
}
func watch(acmeFile string, baseConfig *dumper.BaseConfig) error { func watch(acmeFile string, baseConfig *dumper.BaseConfig) error {
watcher, err := fsnotify.NewWatcher() watcher, err := fsnotify.NewWatcher()
if err != nil { if err != nil {
return err return fmt.Errorf("failed to create new watcher: %w", err)
} }
defer func() { _ = watcher.Close() }() defer func() { _ = watcher.Close() }()
@ -114,7 +135,7 @@ func watch(acmeFile string, baseConfig *dumper.BaseConfig) error {
err = watcher.Add(acmeFile) err = watcher.Add(acmeFile)
if err != nil { if err != nil {
return err return fmt.Errorf("failed to add a new watcher: %w", err)
} }
<-done <-done
@ -125,12 +146,12 @@ func watch(acmeFile string, baseConfig *dumper.BaseConfig) error {
func manageEvent(watcher *fsnotify.Watcher, event fsnotify.Event, acmeFile string, previousHash []byte, baseConfig *dumper.BaseConfig) ([]byte, error) { func manageEvent(watcher *fsnotify.Watcher, event fsnotify.Event, acmeFile string, previousHash []byte, baseConfig *dumper.BaseConfig) ([]byte, error) {
err := manageRename(watcher, event, acmeFile) err := manageRename(watcher, event, acmeFile)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("watcher renewal failed: %w", err)
} }
hash, err := calculateHash(acmeFile) hash, err := calculateHash(acmeFile)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("file hash calculation failed: %w", err)
} }
if !bytes.Equal(previousHash, hash) { if !bytes.Equal(previousHash, hash) {

View File

@ -45,13 +45,15 @@ type DomainsCertificate struct {
// convertOldAccount converts account information from old account format. // convertOldAccount converts account information from old account format.
func convertOldAccount(account *AccountOld) *v1.StoredData { func convertOldAccount(account *AccountOld) *v1.StoredData {
storedData := &v1.StoredData{} storedData := &v1.StoredData{
storedData.Account = &v1.Account{ Account: &v1.Account{
PrivateKey: account.PrivateKey, PrivateKey: account.PrivateKey,
Registration: account.Registration, Registration: account.Registration,
Email: account.Email, Email: account.Email,
KeyType: account.KeyType, KeyType: account.KeyType,
},
} }
var certs []*v1.Certificate var certs []*v1.Certificate
for _, oldCert := range account.DomainsCertificate.Certs { for _, oldCert := range account.DomainsCertificate.Certs {
certs = append(certs, &v1.Certificate{ certs = append(certs, &v1.Certificate{
@ -61,5 +63,6 @@ func convertOldAccount(account *AccountOld) *v1.StoredData {
}) })
} }
storedData.Certificates = certs storedData.Certificates = certs
return storedData return storedData
} }

View File

@ -24,7 +24,7 @@ const DefaultStoreKeySuffix = "/acme/account/object"
func Dump(config *Config, baseConfig *dumper.BaseConfig) error { func Dump(config *Config, baseConfig *dumper.BaseConfig) error {
kvStore, err := valkeyrie.NewStore(config.Backend, config.Endpoints, config.Options) kvStore, err := valkeyrie.NewStore(config.Backend, config.Endpoints, config.Options)
if err != nil { if err != nil {
return fmt.Errorf("unable to create client of the store: %v", err) return fmt.Errorf("unable to create client of the store: %w", err)
} }
storeKey := config.Prefix + config.Suffix storeKey := config.Prefix + config.Suffix
@ -35,7 +35,7 @@ func Dump(config *Config, baseConfig *dumper.BaseConfig) error {
pair, err := kvStore.Get(storeKey, nil) pair, err := kvStore.Get(storeKey, nil)
if err != nil { if err != nil {
return fmt.Errorf("unable to retrieve %s value: %v", storeKey, err) return fmt.Errorf("unable to retrieve %s value: %w", storeKey, err)
} }
return dumpPair(pair, baseConfig) return dumpPair(pair, baseConfig)
@ -80,17 +80,17 @@ func dumpPair(pair *store.KVPair, baseConfig *dumper.BaseConfig) error {
func getStoredDataFromGzip(pair *store.KVPair) (*v1.StoredData, error) { func getStoredDataFromGzip(pair *store.KVPair) (*v1.StoredData, error) {
reader, err := gzip.NewReader(bytes.NewBuffer(pair.Value)) reader, err := gzip.NewReader(bytes.NewBuffer(pair.Value))
if err != nil { if err != nil {
return nil, fmt.Errorf("fail to create GZip reader: %v", err) return nil, fmt.Errorf("fail to create GZip reader: %w", err)
} }
acmeData, err := ioutil.ReadAll(reader) acmeData, err := ioutil.ReadAll(reader)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to read the pair content: %v", err) return nil, fmt.Errorf("unable to read the pair content: %w", err)
} }
account := &AccountOld{} account := &AccountOld{}
if err := json.Unmarshal(acmeData, &account); err != nil { if err := json.Unmarshal(acmeData, &account); err != nil {
return nil, fmt.Errorf("unable marshal AccountOld: %v", err) return nil, fmt.Errorf("unable marshal AccountOld: %w", err)
} }
return convertOldAccount(account), nil return convertOldAccount(account), nil

View File

@ -2,6 +2,7 @@ package v1
import ( import (
"encoding/pem" "encoding/pem"
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
@ -20,29 +21,29 @@ func Dump(data *StoredData, baseConfig *dumper.BaseConfig) error {
if baseConfig.Clean { if baseConfig.Clean {
err := cleanDir(baseConfig.DumpPath) err := cleanDir(baseConfig.DumpPath)
if err != nil { if err != nil {
return err return fmt.Errorf("folder cleaning failed: %w", err)
} }
} }
if !baseConfig.DomainSubDir { if !baseConfig.DomainSubDir {
if err := os.MkdirAll(filepath.Join(baseConfig.DumpPath, certsSubDir), 0755); err != nil { if err := os.MkdirAll(filepath.Join(baseConfig.DumpPath, certsSubDir), 0755); err != nil {
return err return fmt.Errorf("certs folder creation failure: %w", err)
} }
} }
if err := os.MkdirAll(filepath.Join(baseConfig.DumpPath, keysSubDir), 0755); err != nil { if err := os.MkdirAll(filepath.Join(baseConfig.DumpPath, keysSubDir), 0755); err != nil {
return err return fmt.Errorf("keys folder creation failure: %w", err)
} }
for _, cert := range data.Certificates { for _, cert := range data.Certificates {
err := writeCert(baseConfig.DumpPath, cert, baseConfig.CrtInfo, baseConfig.DomainSubDir) err := writeCert(baseConfig.DumpPath, cert, baseConfig.CrtInfo, baseConfig.DomainSubDir)
if err != nil { if err != nil {
return err return fmt.Errorf("failed to write certificates: %w", err)
} }
err = writeKey(baseConfig.DumpPath, cert, baseConfig.KeyInfo, baseConfig.DomainSubDir) err = writeKey(baseConfig.DumpPath, cert, baseConfig.KeyInfo, baseConfig.DomainSubDir)
if err != nil { if err != nil {
return err return fmt.Errorf("failed to write certificate keys: %w", err)
} }
} }

View File

@ -2,6 +2,7 @@ package v2
import ( import (
"encoding/pem" "encoding/pem"
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
@ -21,30 +22,30 @@ func Dump(data map[string]*acme.StoredData, baseConfig *dumper.BaseConfig) error
if baseConfig.Clean { if baseConfig.Clean {
err := cleanDir(baseConfig.DumpPath) err := cleanDir(baseConfig.DumpPath)
if err != nil { if err != nil {
return err return fmt.Errorf("folder cleaning failed: %w", err)
} }
} }
if !baseConfig.DomainSubDir { if !baseConfig.DomainSubDir {
if err := os.MkdirAll(filepath.Join(baseConfig.DumpPath, certsSubDir), 0755); err != nil { if err := os.MkdirAll(filepath.Join(baseConfig.DumpPath, certsSubDir), 0755); err != nil {
return err return fmt.Errorf("certs folder creation failure: %w", err)
} }
} }
if err := os.MkdirAll(filepath.Join(baseConfig.DumpPath, keysSubDir), 0755); err != nil { if err := os.MkdirAll(filepath.Join(baseConfig.DumpPath, keysSubDir), 0755); err != nil {
return err return fmt.Errorf("keys folder creation failure: %w", err)
} }
for _, store := range data { for _, store := range data {
for _, cert := range store.Certificates { for _, cert := range store.Certificates {
err := writeCert(baseConfig.DumpPath, cert.Certificate, baseConfig.CrtInfo, baseConfig.DomainSubDir) err := writeCert(baseConfig.DumpPath, cert.Certificate, baseConfig.CrtInfo, baseConfig.DomainSubDir)
if err != nil { if err != nil {
return err return fmt.Errorf("failed to write certificates: %w", err)
} }
err = writeKey(baseConfig.DumpPath, cert.Certificate, baseConfig.KeyInfo, baseConfig.DomainSubDir) err = writeKey(baseConfig.DumpPath, cert.Certificate, baseConfig.KeyInfo, baseConfig.DomainSubDir)
if err != nil { if err != nil {
return err return fmt.Errorf("failed to write certificate keys: %w", err)
} }
} }
@ -56,7 +57,7 @@ func Dump(data map[string]*acme.StoredData, baseConfig *dumper.BaseConfig) error
err := ioutil.WriteFile(filepath.Join(baseConfig.DumpPath, keysSubDir, "letsencrypt"+baseConfig.KeyInfo.Ext), privateKeyPem, 0600) err := ioutil.WriteFile(filepath.Join(baseConfig.DumpPath, keysSubDir, "letsencrypt"+baseConfig.KeyInfo.Ext), privateKeyPem, 0600)
if err != nil { if err != nil {
return err return fmt.Errorf("failed to write private key: %w", err)
} }
} }