-
Notifications
You must be signed in to change notification settings - Fork 17
/
supervisor.go
136 lines (113 loc) · 3.44 KB
/
supervisor.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package main
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"net/http"
"os"
"strings"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/pkg/stdcopy"
)
type SupervisorResponse struct {
Result string `json:"result"`
Message string `json:"message,omitempty"`
Data map[string]interface{} `json:"data,omitempty"`
}
type SupervisorInfo struct {
Healthy bool `json:"healthy"`
Supported bool `json:"supported"`
}
type ResolutionInfo struct {
Unhealthy []string `json:"unhealthy"`
Unsupported []string `json:"unsupported"`
}
type SupervisorPing struct {
Connected bool
State string
}
func supervisorApiProxy(path string) (SupervisorResponse, error) {
var jsonResponse SupervisorResponse
request, _ := http.NewRequest("GET", fmt.Sprintf("http://supervisor/%s", path), nil)
request.Header = http.Header{
"Authorization": []string{fmt.Sprintf("Bearer %s", os.Getenv("SUPERVISOR_TOKEN"))},
}
response, err := httpClient.Do(request)
if err != nil {
log.Printf("Supervisor API call failed with error %s", err)
return jsonResponse, err
}
if response.StatusCode >= 300 && response.StatusCode != 400 {
log.Printf("Supervisor API call failed with status code %v", response.StatusCode)
return jsonResponse, fmt.Errorf("Supervisor API call failed with status code %v", response.StatusCode)
}
bodyBytes, err := io.ReadAll(response.Body)
if err != nil {
return jsonResponse, err
}
defer response.Body.Close()
json.Unmarshal([]byte(bodyBytes), &jsonResponse)
if response.StatusCode == 400 {
return jsonResponse, errors.New("Supervisor API call failed with status code 400")
}
return jsonResponse, err
}
func supervisorPing() SupervisorPing {
supervisorPingData := SupervisorPing{
Connected: true,
}
data, err := supervisorApiProxy("supervisor/ping")
if err != nil {
log.Printf("Supervisor ping failed with error %s", err)
supervisorPingData.Connected = false
if strings.HasPrefix(data.Message, "System is not ready with state:") {
// This is an API error, but we got a proper response so we accept it
supervisorPingData.Connected = true
supervisorPingData.State = strings.ReplaceAll(data.Message, "System is not ready with state: ", "")
}
}
return supervisorPingData
}
func getSupervisorInfo() (SupervisorInfo, error) {
var supervisorInfo SupervisorInfo
response, err := supervisorApiProxy("supervisor/info")
if err != nil {
log.Printf("Supervisor API call failed with error %s", err)
return supervisorInfo, err
}
jsonData, _ := json.Marshal(response.Data)
json.Unmarshal(jsonData, &supervisorInfo)
return supervisorInfo, nil
}
func getResolutionInfo() (ResolutionInfo, error) {
var resolutionInfo ResolutionInfo
response, err := supervisorApiProxy("resolution/info")
if err != nil {
log.Printf("Supervisor API call failed with error %s", err)
return resolutionInfo, err
}
jsonData, _ := json.Marshal(response.Data)
json.Unmarshal(jsonData, &resolutionInfo)
return resolutionInfo, nil
}
func supervisorLogs(w io.Writer) error {
// Read logs from container
reader, err := cli.ContainerLogs(context.Background(), "hassio_supervisor", container.LogsOptions{
ShowStdout: true,
ShowStderr: true,
Follow: false,
Timestamps: false,
Tail: "all",
})
if err != nil {
log.Printf("Can't get supervisor logs %s", err)
return err
}
defer reader.Close()
// Return the content
_, err = stdcopy.StdCopy(w, w, reader)
return err
}