blob: 82638035213dc0612c573666fae3260c2f47e731 [file] [log] [blame]
giof8acc612025-04-26 08:20:55 +04001package status
2
gioda708652025-04-30 14:57:38 +04003import (
4 "bytes"
5 "encoding/json"
6 "fmt"
gioea6d9122025-05-22 17:57:18 +04007 "strings"
gioda708652025-04-30 14:57:38 +04008)
9
giof8acc612025-04-26 08:20:55 +040010type InstanceMonitor struct {
11 m Monitor
gioda708652025-04-30 14:57:38 +040012 instances map[string]ResourceOuts
giof8acc612025-04-26 08:20:55 +040013}
14
15func NewInstanceMonitor(m Monitor) *InstanceMonitor {
16 return &InstanceMonitor{
17 m: m,
gioda708652025-04-30 14:57:38 +040018 instances: map[string]ResourceOuts{},
giof8acc612025-04-26 08:20:55 +040019 }
20}
21
gioda708652025-04-30 14:57:38 +040022func (m *InstanceMonitor) Monitor(id string, resources ResourceOuts) {
giof8acc612025-04-26 08:20:55 +040023 m.instances[id] = resources
24}
25
gioda708652025-04-30 14:57:38 +040026func (m *InstanceMonitor) Get(id string) (map[DodoResource]Status, error) {
27 ret := map[DodoResource]Status{}
28 namespace := m.instances[id].Release.Namespace
29 for _, out := range m.instances[id].Outs {
30 if _, err := m.monitor(namespace, DodoResource{"internal", out.Name}, out, ret); err != nil {
31 return nil, err
giof8acc612025-04-26 08:20:55 +040032 }
33 }
gioda708652025-04-30 14:57:38 +040034 for i := range ret {
35 if i.Type == "internal" {
36 delete(ret, i)
37 }
38 }
39 return ret, nil
40}
41
42func mergeStatus(a Status, b Status) Status {
43 if a > b {
44 return a
45 } else {
46 return b
47 }
48}
49
50// TODO(gio): handle volume
51func (m *InstanceMonitor) monitor(namespace string, resource DodoResource, out ResourceOut, ret map[DodoResource]Status) (Status, error) {
52 status := StatusNoStatus
gioea6d9122025-05-22 17:57:18 +040053 if resource.Type == "ingress" {
54 var err error
55 status, err = m.m.Get(Resource{
56 Type: ResourceIngress,
gioda708652025-04-30 14:57:38 +040057 ResourceRef: ResourceRef{
gioea6d9122025-05-22 17:57:18 +040058 Id: out.Id,
59 Name: fmt.Sprintf("ingress-%s", strings.TrimPrefix(resource.Name, "https://")),
gioda708652025-04-30 14:57:38 +040060 Namespace: namespace,
61 },
62 })
gioda708652025-04-30 14:57:38 +040063 if err != nil {
64 return StatusNoStatus, err
65 }
gioea6d9122025-05-22 17:57:18 +040066 } else {
67 for _, h := range out.Helm {
68 hs, err := m.m.Get(Resource{
69 Type: ResourceHelmRelease,
70 ResourceRef: ResourceRef{
71 Id: h.Id,
72 Name: h.Name,
73 Namespace: namespace,
74 },
75 })
76 if err != nil {
77 return StatusNoStatus, err
78 }
79 status = mergeStatus(status, hs)
80 }
gioda708652025-04-30 14:57:38 +040081 }
gio0af17d62025-05-01 15:36:00 +040082 for _, i := range out.Volume {
83 if s, err := m.monitor(namespace, DodoResource{"volume", i.Name}, i, ret); err != nil {
84 return StatusNoStatus, err
85 } else {
gioea6d9122025-05-22 17:57:18 +040086 status = mergeStatus(status, s)
gio0af17d62025-05-01 15:36:00 +040087 }
88 }
gioda708652025-04-30 14:57:38 +040089 for _, i := range out.PostgreSQL {
90 if s, err := m.monitor(namespace, DodoResource{"postgresql", i.Name}, i, ret); err != nil {
91 return StatusNoStatus, err
92 } else {
gioea6d9122025-05-22 17:57:18 +040093 status = mergeStatus(status, s)
gioda708652025-04-30 14:57:38 +040094 }
95 }
96 for _, i := range out.MongoDB {
97 if s, err := m.monitor(namespace, DodoResource{"mongodb", i.Name}, i, ret); err != nil {
98 return StatusNoStatus, err
99 } else {
gioea6d9122025-05-22 17:57:18 +0400100 status = mergeStatus(status, s)
gioda708652025-04-30 14:57:38 +0400101 }
102 }
103 for _, i := range out.Ingress {
104 name := fmt.Sprintf("https://%s.%s", i.Subdomain, i.Network.Domain)
105 if s, err := m.monitor(namespace, DodoResource{"ingress", name}, i.ResourceOut, ret); err != nil {
106 return StatusNoStatus, err
107 } else {
gioea6d9122025-05-22 17:57:18 +0400108 status = mergeStatus(status, s)
gioda708652025-04-30 14:57:38 +0400109 }
110 }
gioa6024622025-05-01 18:37:16 +0400111 for _, i := range out.Services {
112 if s, err := m.monitor(namespace, DodoResource{"service", i.Name}, i, ret); err != nil {
113 return StatusNoStatus, err
114 } else {
gioea6d9122025-05-22 17:57:18 +0400115 status = mergeStatus(status, s)
gioa6024622025-05-01 18:37:16 +0400116 }
117 }
gioda708652025-04-30 14:57:38 +0400118 ret[resource] = status
119 return status, nil
120}
121
122type resourceIngress struct {
123 ResourceOut
124 Network struct {
125 Domain string `json:"domain"`
126 } `json:"network"`
127 Subdomain string `json:"subdomain"`
128}
129
130type resourceHelm struct {
131 Id string `json:"id"`
132 Name string `json:"name"`
133}
134
135type ResourceOut struct {
gioea6d9122025-05-22 17:57:18 +0400136 Id string `json:"id"`
gioda708652025-04-30 14:57:38 +0400137 Name string `json:"name"`
gio0af17d62025-05-01 15:36:00 +0400138 Volume map[string]ResourceOut `json:"volume"`
gioda708652025-04-30 14:57:38 +0400139 PostgreSQL map[string]ResourceOut `json:"postgresql"`
140 MongoDB map[string]ResourceOut `json:"mongodb"`
141 Ingress map[string]resourceIngress `json:"ingress"`
gioa6024622025-05-01 18:37:16 +0400142 Services map[string]ResourceOut `json:"services"`
gioda708652025-04-30 14:57:38 +0400143 Helm map[string]resourceHelm `json:"helmR"`
144}
145
146type ResourceOuts struct {
147 Release struct {
148 Namespace string `json:"namespace"`
149 }
150 Outs map[string]ResourceOut `json:"outs"`
151}
152
153type DodoResource struct {
154 Type string
155 Name string
156}
157
158type DodoResourceStatus struct {
159 Type string `json:"type"`
160 Name string `json:"name"`
161 Status string `json:"status"`
162}
163
164func DecodeResourceOuts(raw []byte) (ResourceOuts, error) {
165 var outs ResourceOuts
166 if err := json.NewDecoder(bytes.NewReader(raw)).Decode(&outs); err != nil {
167 return ResourceOuts{}, err
168 }
169 return outs, nil
giof8acc612025-04-26 08:20:55 +0400170}