1
0
Fork 0

Update lego.

This commit is contained in:
Fernandez Ludovic 2019-06-11 23:11:17 +02:00 committed by Traefiker Bot
parent 63c3ed3931
commit 0034bef6b9
27 changed files with 1663 additions and 14 deletions

View file

@ -0,0 +1,113 @@
package client
import (
"encoding/json"
"errors"
"fmt"
"github.com/labbsr0x/bindman-dns-webhook/src/types"
"github.com/labbsr0x/goh/gohclient"
"net/http"
"strings"
)
const recordsPath = "/records"
// DNSWebhookClient defines the basic structure of a DNS Listener
type DNSWebhookClient struct {
ClientAPI gohclient.API
}
// New builds the client to communicate with the dns manager
func New(managerAddress string, httpClient *http.Client) (*DNSWebhookClient, error) {
if strings.TrimSpace(managerAddress) == "" {
return nil, errors.New("managerAddress parameter must be a non-empty string")
}
client, err := gohclient.New(httpClient, managerAddress)
if err != nil {
return nil, err
}
client.Accept = "application/json"
client.ContentType = "application/json"
client.UserAgent = "bindman-dns-webhook-client"
return &DNSWebhookClient{
ClientAPI: client,
}, nil
}
// GetRecords communicates with the dns manager and gets the DNS Records
func (l *DNSWebhookClient) GetRecords() (result []types.DNSRecord, err error) {
resp, data, err := l.ClientAPI.Get(recordsPath)
if err != nil {
return
}
if resp.StatusCode == http.StatusOK {
err = json.Unmarshal(data, &result)
} else {
err = parseResponseBodyToError(data)
}
return
}
// GetRecord communicates with the dns manager and gets a DNS Record
func (l *DNSWebhookClient) GetRecord(name, recordType string) (result types.DNSRecord, err error) {
resp, data, err := l.ClientAPI.Get(fmt.Sprintf(recordsPath+"/%s/%s", name, recordType))
if err != nil {
return
}
if resp.StatusCode == http.StatusOK {
err = json.Unmarshal(data, &result)
} else {
err = parseResponseBodyToError(data)
}
return
}
// AddRecord adds a DNS record
func (l *DNSWebhookClient) AddRecord(name string, recordType string, value string) error {
return l.addOrUpdateRecord(&types.DNSRecord{Value: value, Name: name, Type: recordType}, l.ClientAPI.Post)
}
// UpdateRecord is a function that calls the defined webhook to update a specific dns record
func (l *DNSWebhookClient) UpdateRecord(record *types.DNSRecord) error {
return l.addOrUpdateRecord(record, l.ClientAPI.Put)
}
// addOrUpdateRecord .
func (l *DNSWebhookClient) addOrUpdateRecord(record *types.DNSRecord, action func(url string, body []byte) (*http.Response, []byte, error)) error {
if errs := record.Check(); errs != nil {
return fmt.Errorf("invalid DNS Record: %v", strings.Join(errs, ", "))
}
mr, err := json.Marshal(record)
if err != nil {
return err
}
resp, data, err := action(recordsPath, mr)
if err != nil {
return err
}
if resp.StatusCode != http.StatusNoContent {
return parseResponseBodyToError(data)
}
return nil
}
// RemoveRecord is a function that calls the defined webhook to remove a specific dns record
func (l *DNSWebhookClient) RemoveRecord(name, recordType string) error {
resp, data, err := l.ClientAPI.Delete(fmt.Sprintf(recordsPath+"/%s/%s", name, recordType))
if err != nil {
return err
}
if resp.StatusCode != http.StatusNoContent {
return parseResponseBodyToError(data)
}
return err
}
func parseResponseBodyToError(data []byte) error {
var err types.Error
if errUnmarshal := json.Unmarshal(data, &err); errUnmarshal != nil {
return errUnmarshal
}
return &err
}

View file

@ -0,0 +1,20 @@
package types
// DNSManager defines the operations a DNS Manager provider should implement
type DNSManager interface {
// GetDNSRecords retrieves all the dns records being managed
GetDNSRecords() ([]DNSRecord, error)
// GetDNSRecord retrieves the dns record identified by name
GetDNSRecord(name, recordType string) (*DNSRecord, error)
// RemoveDNSRecord removes a DNS record
RemoveDNSRecord(name, recordType string) error
// AddDNSRecord adds a new DNS record
AddDNSRecord(record DNSRecord) error
// UpdateDNSRecord updates an existing DNS record
UpdateDNSRecord(record DNSRecord) error
}

View file

@ -0,0 +1,40 @@
package types
import (
"fmt"
"strings"
"github.com/sirupsen/logrus"
)
// DNSRecord defines what we understand as a DNSRecord
type DNSRecord struct {
// Name the DNS host name
Name string `json:"name"`
// Value the value of this record
Value string `json:"value"`
// Type the record type
Type string `json:"type"`
}
// Check verifies if the DNS record satisfies certain conditions
func (record *DNSRecord) Check() []string {
logrus.Infof("Record to check: '%v'", record)
emptyValueErrorMessage := "the value of field '%s' cannot be empty"
var errs []string
if strings.TrimSpace(record.Name) == "" {
errs = append(errs, fmt.Sprintf(emptyValueErrorMessage, "name"))
}
if strings.TrimSpace(record.Value) == "" {
errs = append(errs, fmt.Sprintf(emptyValueErrorMessage, "value"))
}
if strings.TrimSpace(record.Type) == "" {
errs = append(errs, fmt.Sprintf(emptyValueErrorMessage, "type"))
}
return errs
}

View file

@ -0,0 +1,51 @@
package types
import (
"fmt"
"github.com/sirupsen/logrus"
"net/http"
)
// Error groups together information that defines an error. Should always be used to
type Error struct {
Message string `json:"message"`
Code int `json:"code"`
Details []string `json:"details,omitempty"`
Err error `json:"-"`
}
// Error() gives a string representing the error; also, forces the Error type to comply with the error interface
func (e *Error) Error() string {
msg := fmt.Sprintf("ERROR (%v): %s; \n Inner error: %s", e.Code, e.Message, e.Err)
logrus.Debug(msg)
return msg
}
// BadRequestError create an Error instance with http.StatusBadRequest code
func BadRequestError(message string, err error, details ...string) *Error {
return &Error{Message: message, Err: err, Code: http.StatusBadRequest, Details: details}
}
// BadRequestError create an Error instance with http.StatusNotFound code
func NotFoundError(message string, err error, details ...string) *Error {
return &Error{Message: message, Err: err, Code: http.StatusNotFound, Details: details}
}
// BadRequestError create an Error instance with http.StatusInternalServerError code
func InternalServerError(message string, err error, details ...string) *Error {
return &Error{Message: message, Err: err, Code: http.StatusInternalServerError, Details: details}
}
// PanicIfError is just a wrapper to a panic call that propagates error when it's not nil
func PanicIfError(e error) {
if e != nil {
logrus.Errorf(e.Error())
panic(e)
}
}
// Panic wraps a panic call propagating the given error parameter
func Panic(e Error) {
logrus.Errorf(e.Error())
panic(e)
}