feat: improve error handling.
- skip EOF error
This commit is contained in:
parent
8c8f1ea37f
commit
1ef3d37498
@ -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) {
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user