mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-07-04 01:07:49 +02:00
all: add sending logs to ControlD API
This commit is contained in:
committed by
Cuong Manh Le
parent
f5ba8be182
commit
a63a30c76b
+1
-1
@@ -1269,7 +1269,7 @@ func run(appCallback *AppCallback, stopCh chan struct{}) {
|
|||||||
|
|
||||||
cdLogger := mainLog.Load().With().Str("mode", "cd").Logger()
|
cdLogger := mainLog.Load().With().Str("mode", "cd").Logger()
|
||||||
// Performs self-uninstallation if the ControlD device does not exist.
|
// Performs self-uninstallation if the ControlD device does not exist.
|
||||||
var uer *controld.UtilityErrorResponse
|
var uer *controld.ErrorResponse
|
||||||
if errors.As(err, &uer) && uer.ErrorField.Code == controld.InvalidConfigCode {
|
if errors.As(err, &uer) && uer.ErrorField.Code == controld.InvalidConfigCode {
|
||||||
_ = uninstallInvalidCdUID(p, cdLogger, false)
|
_ = uninstallInvalidCdUID(p, cdLogger, false)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1044,7 +1044,7 @@ func dnsChanged(iface *net.Interface, nameservers []string) bool {
|
|||||||
|
|
||||||
// selfUninstallCheck checks if the error dues to controld.InvalidConfigCode, perform self-uninstall then.
|
// selfUninstallCheck checks if the error dues to controld.InvalidConfigCode, perform self-uninstall then.
|
||||||
func selfUninstallCheck(uninstallErr error, p *prog, logger zerolog.Logger) {
|
func selfUninstallCheck(uninstallErr error, p *prog, logger zerolog.Logger) {
|
||||||
var uer *controld.UtilityErrorResponse
|
var uer *controld.ErrorResponse
|
||||||
if errors.As(uninstallErr, &uer) && uer.ErrorField.Code == controld.InvalidConfigCode {
|
if errors.As(uninstallErr, &uer) && uer.ErrorField.Code == controld.InvalidConfigCode {
|
||||||
p.stopDnsWatchers()
|
p.stopDnsWatchers()
|
||||||
|
|
||||||
|
|||||||
+90
-38
@@ -25,8 +25,12 @@ import (
|
|||||||
const (
|
const (
|
||||||
apiDomainCom = "api.controld.com"
|
apiDomainCom = "api.controld.com"
|
||||||
apiDomainDev = "api.controld.dev"
|
apiDomainDev = "api.controld.dev"
|
||||||
resolverDataURLCom = "https://api.controld.com/utility"
|
apiURLCom = "https://api.controld.com"
|
||||||
resolverDataURLDev = "https://api.controld.dev/utility"
|
apiURLDev = "https://api.controld.dev"
|
||||||
|
resolverDataURLCom = apiURLCom + "/utility"
|
||||||
|
resolverDataURLDev = apiURLDev + "/utility"
|
||||||
|
logURLCom = apiURLCom + "/logs"
|
||||||
|
logURLDev = apiURLDev + "/logs"
|
||||||
InvalidConfigCode = 40402
|
InvalidConfigCode = 40402
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -49,14 +53,14 @@ type utilityResponse struct {
|
|||||||
} `json:"body"`
|
} `json:"body"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UtilityErrorResponse struct {
|
type ErrorResponse struct {
|
||||||
ErrorField struct {
|
ErrorField struct {
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
Code int `json:"code"`
|
Code int `json:"code"`
|
||||||
} `json:"error"`
|
} `json:"error"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u UtilityErrorResponse) Error() string {
|
func (u ErrorResponse) Error() string {
|
||||||
return u.ErrorField.Message
|
return u.ErrorField.Message
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,6 +75,12 @@ type UtilityOrgRequest struct {
|
|||||||
Hostname string `json:"hostname"`
|
Hostname string `json:"hostname"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LogsRequest contains request data for sending runtime logs to API.
|
||||||
|
type LogsRequest struct {
|
||||||
|
UID string `json:"uid"`
|
||||||
|
LogFile string `json:"log_file"`
|
||||||
|
}
|
||||||
|
|
||||||
// FetchResolverConfig fetch Control D config for given uid.
|
// FetchResolverConfig fetch Control D config for given uid.
|
||||||
func FetchResolverConfig(rawUID, version string, cdDev bool) (*ResolverConfig, error) {
|
func FetchResolverConfig(rawUID, version string, cdDev bool) (*ResolverConfig, error) {
|
||||||
uid, clientID := ParseRawUID(rawUID)
|
uid, clientID := ParseRawUID(rawUID)
|
||||||
@@ -123,6 +133,81 @@ func postUtilityAPI(version string, cdDev, lastUpdatedFailed bool, body io.Reade
|
|||||||
}
|
}
|
||||||
req.URL.RawQuery = q.Encode()
|
req.URL.RawQuery = q.Encode()
|
||||||
req.Header.Add("Content-Type", "application/json")
|
req.Header.Add("Content-Type", "application/json")
|
||||||
|
transport := apiTransport(cdDev)
|
||||||
|
client := http.Client{
|
||||||
|
Timeout: 10 * time.Second,
|
||||||
|
Transport: transport,
|
||||||
|
}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("postUtilityAPI client.Do: %w", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
d := json.NewDecoder(resp.Body)
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
errResp := &ErrorResponse{}
|
||||||
|
if err := d.Decode(errResp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nil, errResp
|
||||||
|
}
|
||||||
|
|
||||||
|
ur := &utilityResponse{}
|
||||||
|
if err := d.Decode(ur); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &ur.Body.Resolver, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendLogs sends runtime log to ControlD API.
|
||||||
|
func SendLogs(req *LogsRequest, cdDev bool) error {
|
||||||
|
body, _ := json.Marshal(req)
|
||||||
|
return postLogAPI(cdDev, bytes.NewReader(body))
|
||||||
|
}
|
||||||
|
|
||||||
|
func postLogAPI(cdDev bool, body io.Reader) error {
|
||||||
|
apiUrl := logURLCom
|
||||||
|
if cdDev {
|
||||||
|
apiUrl = logURLDev
|
||||||
|
}
|
||||||
|
req, err := http.NewRequest("POST", apiUrl, body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("http.NewRequest: %w", err)
|
||||||
|
}
|
||||||
|
transport := apiTransport(cdDev)
|
||||||
|
client := http.Client{
|
||||||
|
Timeout: 10 * time.Second,
|
||||||
|
Transport: transport,
|
||||||
|
}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("postLogAPI client.Do: %w", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
d := json.NewDecoder(resp.Body)
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
errResp := &ErrorResponse{}
|
||||||
|
if err := d.Decode(errResp); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return errResp
|
||||||
|
}
|
||||||
|
_, _ = io.Copy(io.Discard, resp.Body)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseRawUID parse the input raw UID, returning real UID and ClientID.
|
||||||
|
// The raw UID can have 2 forms:
|
||||||
|
//
|
||||||
|
// - <uid>
|
||||||
|
// - <uid>/<client_id>
|
||||||
|
func ParseRawUID(rawUID string) (string, string) {
|
||||||
|
uid, clientID, _ := strings.Cut(rawUID, "/")
|
||||||
|
return uid, clientID
|
||||||
|
}
|
||||||
|
|
||||||
|
// apiTransport returns an HTTP transport for connecting to ControlD API endpoint.
|
||||||
|
func apiTransport(cdDev bool) *http.Transport {
|
||||||
transport := http.DefaultTransport.(*http.Transport).Clone()
|
transport := http.DefaultTransport.(*http.Transport).Clone()
|
||||||
transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
apiDomain := apiDomainCom
|
apiDomain := apiDomainCom
|
||||||
@@ -143,41 +228,8 @@ func postUtilityAPI(version string, cdDev, lastUpdatedFailed bool, body io.Reade
|
|||||||
d := &ctrldnet.ParallelDialer{}
|
d := &ctrldnet.ParallelDialer{}
|
||||||
return d.DialContext(ctx, network, addrs)
|
return d.DialContext(ctx, network, addrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if router.Name() == ddwrt.Name || runtime.GOOS == "android" {
|
if router.Name() == ddwrt.Name || runtime.GOOS == "android" {
|
||||||
transport.TLSClientConfig = &tls.Config{RootCAs: certs.CACertPool()}
|
transport.TLSClientConfig = &tls.Config{RootCAs: certs.CACertPool()}
|
||||||
}
|
}
|
||||||
client := http.Client{
|
return transport
|
||||||
Timeout: 10 * time.Second,
|
|
||||||
Transport: transport,
|
|
||||||
}
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("client.Do: %w", err)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
d := json.NewDecoder(resp.Body)
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
errResp := &UtilityErrorResponse{}
|
|
||||||
if err := d.Decode(errResp); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return nil, errResp
|
|
||||||
}
|
|
||||||
|
|
||||||
ur := &utilityResponse{}
|
|
||||||
if err := d.Decode(ur); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &ur.Body.Resolver, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseRawUID parse the input raw UID, returning real UID and ClientID.
|
|
||||||
// The raw UID can have 2 forms:
|
|
||||||
//
|
|
||||||
// - <uid>
|
|
||||||
// - <uid>/<client_id>
|
|
||||||
func ParseRawUID(rawUID string) (string, string) {
|
|
||||||
uid, clientID, _ := strings.Cut(rawUID, "/")
|
|
||||||
return uid, clientID
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user