blob: 542f70d0fd44e0aa57f06b8ffff298ffb2b0096c [file] [log] [blame]
gio3af43942024-04-16 08:13:50 +04001package installer
2
3import (
4 "fmt"
gio09a3e5b2024-04-26 14:11:06 +04005 "html/template"
gio3af43942024-04-16 08:13:50 +04006)
7
8type Release struct {
gio3cdee592024-04-17 10:15:56 +04009 AppInstanceId string `json:"appInstanceId"`
10 Namespace string `json:"namespace"`
11 RepoAddr string `json:"repoAddr"`
12 AppDir string `json:"appDir"`
giof8843412024-05-22 16:38:05 +040013 ImageRegistry string `json:"imageRegistry,omitempty"`
gio3af43942024-04-16 08:13:50 +040014}
15
16type Network struct {
17 Name string `json:"name,omitempty"`
18 IngressClass string `json:"ingressClass,omitempty"`
19 CertificateIssuer string `json:"certificateIssuer,omitempty"`
20 Domain string `json:"domain,omitempty"`
21 AllocatePortAddr string `json:"allocatePortAddr,omitempty"`
gioefa0ed42024-06-13 12:31:43 +040022 ReservePortAddr string `json:"reservePortAddr,omitempty"`
gio3af43942024-04-16 08:13:50 +040023}
24
gioe72b54f2024-04-22 10:44:41 +040025type InfraAppInstanceConfig struct {
26 Id string `json:"id"`
27 AppId string `json:"appId"`
28 Infra InfraConfig `json:"infra"`
29 Release Release `json:"release"`
30 Values map[string]any `json:"values"`
31 Input map[string]any `json:"input"`
gio09a3e5b2024-04-26 14:11:06 +040032 URL string `json:"url"`
33 Help []HelpDocument `json:"help"`
34 Icon template.HTML `json:"icon"`
gioe72b54f2024-04-22 10:44:41 +040035}
36
gio3cdee592024-04-17 10:15:56 +040037type AppInstanceConfig struct {
gio3af43942024-04-16 08:13:50 +040038 Id string `json:"id"`
39 AppId string `json:"appId"`
gioe72b54f2024-04-22 10:44:41 +040040 Env EnvConfig `json:"env"`
gio3cdee592024-04-17 10:15:56 +040041 Release Release `json:"release"`
42 Values map[string]any `json:"values"`
43 Input map[string]any `json:"input"`
gio09a3e5b2024-04-26 14:11:06 +040044 URL string `json:"url"`
Davit Tabidze56f86a42024-04-09 19:15:25 +040045 Help []HelpDocument `json:"help"`
gio09a3e5b2024-04-26 14:11:06 +040046 Icon string `json:"icon"`
gio3af43942024-04-16 08:13:50 +040047}
48
gio3cdee592024-04-17 10:15:56 +040049func (a AppInstanceConfig) InputToValues(schema Schema) map[string]any {
50 ret, err := derivedToConfig(a.Input, schema)
gio3af43942024-04-16 08:13:50 +040051 if err != nil {
gio3cdee592024-04-17 10:15:56 +040052 panic(err)
gio3af43942024-04-16 08:13:50 +040053 }
54 return ret
55}
56
57func deriveValues(values any, schema Schema, networks []Network) (map[string]any, error) {
58 ret := make(map[string]any)
gio44f621b2024-04-29 09:44:38 +040059 for _, f := range schema.Fields() {
60 k := f.Name
61 def := f.Schema
gio3af43942024-04-16 08:13:50 +040062 // TODO(gio): validate that it is map
63 v, ok := values.(map[string]any)[k]
64 // TODO(gio): if missing use default value
65 if !ok {
66 if def.Kind() == KindSSHKey {
67 key, err := NewECDSASSHKeyPair("tmp")
68 if err != nil {
69 return nil, err
70 }
71 ret[k] = map[string]string{
72 "public": string(key.RawAuthorizedKey()),
73 "private": string(key.RawPrivateKey()),
74 }
75 }
76 continue
77 }
78 switch def.Kind() {
79 case KindBoolean:
80 ret[k] = v
81 case KindString:
82 ret[k] = v
83 case KindInt:
84 ret[k] = v
gioefa0ed42024-06-13 12:31:43 +040085 case KindPort:
86 ret[k] = v
gioe72b54f2024-04-22 10:44:41 +040087 case KindArrayString:
88 a, ok := v.([]string)
89 if !ok {
90 return nil, fmt.Errorf("expected string array")
91 }
92 ret[k] = a
gio3af43942024-04-16 08:13:50 +040093 case KindNetwork:
94 n, err := findNetwork(networks, v.(string)) // TODO(giolekva): validate
95 if err != nil {
96 return nil, err
97 }
98 ret[k] = n
99 case KindAuth:
100 r, err := deriveValues(v, AuthSchema, networks)
101 if err != nil {
102 return nil, err
103 }
104 ret[k] = r
105 case KindSSHKey:
106 r, err := deriveValues(v, SSHKeySchema, networks)
107 if err != nil {
108 return nil, err
109 }
110 ret[k] = r
111 case KindStruct:
112 r, err := deriveValues(v, def, networks)
113 if err != nil {
114 return nil, err
115 }
116 ret[k] = r
117 default:
118 return nil, fmt.Errorf("Should not reach!")
119 }
120 }
121 return ret, nil
122}
123
124func derivedToConfig(derived map[string]any, schema Schema) (map[string]any, error) {
125 ret := make(map[string]any)
gio44f621b2024-04-29 09:44:38 +0400126 for _, f := range schema.Fields() {
127 k := f.Name
128 def := f.Schema
gio3af43942024-04-16 08:13:50 +0400129 v, ok := derived[k]
130 // TODO(gio): if missing use default value
131 if !ok {
132 continue
133 }
134 switch def.Kind() {
135 case KindBoolean:
136 ret[k] = v
137 case KindString:
138 ret[k] = v
139 case KindInt:
140 ret[k] = v
gioefa0ed42024-06-13 12:31:43 +0400141 case KindPort:
142 ret[k] = v
gioe72b54f2024-04-22 10:44:41 +0400143 case KindArrayString:
144 a, ok := v.([]string)
145 if !ok {
146 return nil, fmt.Errorf("expected string array")
147 }
148 ret[k] = a
gio3af43942024-04-16 08:13:50 +0400149 case KindNetwork:
150 vm, ok := v.(map[string]any)
151 if !ok {
152 return nil, fmt.Errorf("expected map")
153 }
154 name, ok := vm["name"]
155 if !ok {
156 return nil, fmt.Errorf("expected network name")
157 }
158 ret[k] = name
159 case KindAuth:
160 vm, ok := v.(map[string]any)
161 if !ok {
162 return nil, fmt.Errorf("expected map")
163 }
164 r, err := derivedToConfig(vm, AuthSchema)
165 if err != nil {
166 return nil, err
167 }
168 ret[k] = r
169 case KindSSHKey:
170 vm, ok := v.(map[string]any)
171 if !ok {
172 return nil, fmt.Errorf("expected map")
173 }
174 r, err := derivedToConfig(vm, SSHKeySchema)
175 if err != nil {
176 return nil, err
177 }
178 ret[k] = r
179 case KindStruct:
180 vm, ok := v.(map[string]any)
181 if !ok {
182 return nil, fmt.Errorf("expected map")
183 }
184 r, err := derivedToConfig(vm, def)
185 if err != nil {
186 return nil, err
187 }
188 ret[k] = r
189 default:
190 return nil, fmt.Errorf("Should not reach!")
191 }
192 }
193 return ret, nil
194}
195
196func findNetwork(networks []Network, name string) (Network, error) {
197 for _, n := range networks {
198 if n.Name == name {
199 return n, nil
200 }
201 }
202 return Network{}, fmt.Errorf("Network not found: %s", name)
203}