blob: f623392b7757120783f2ce6c8bbdebba883e4a63 [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"`
22}
23
gioe72b54f2024-04-22 10:44:41 +040024type InfraAppInstanceConfig struct {
25 Id string `json:"id"`
26 AppId string `json:"appId"`
27 Infra InfraConfig `json:"infra"`
28 Release Release `json:"release"`
29 Values map[string]any `json:"values"`
30 Input map[string]any `json:"input"`
gio09a3e5b2024-04-26 14:11:06 +040031 URL string `json:"url"`
32 Help []HelpDocument `json:"help"`
33 Icon template.HTML `json:"icon"`
gioe72b54f2024-04-22 10:44:41 +040034}
35
gio3cdee592024-04-17 10:15:56 +040036type AppInstanceConfig struct {
gio3af43942024-04-16 08:13:50 +040037 Id string `json:"id"`
38 AppId string `json:"appId"`
gioe72b54f2024-04-22 10:44:41 +040039 Env EnvConfig `json:"env"`
gio3cdee592024-04-17 10:15:56 +040040 Release Release `json:"release"`
41 Values map[string]any `json:"values"`
42 Input map[string]any `json:"input"`
gio09a3e5b2024-04-26 14:11:06 +040043 URL string `json:"url"`
Davit Tabidze56f86a42024-04-09 19:15:25 +040044 Help []HelpDocument `json:"help"`
gio09a3e5b2024-04-26 14:11:06 +040045 Icon string `json:"icon"`
gio3af43942024-04-16 08:13:50 +040046}
47
gio3cdee592024-04-17 10:15:56 +040048func (a AppInstanceConfig) InputToValues(schema Schema) map[string]any {
49 ret, err := derivedToConfig(a.Input, schema)
gio3af43942024-04-16 08:13:50 +040050 if err != nil {
gio3cdee592024-04-17 10:15:56 +040051 panic(err)
gio3af43942024-04-16 08:13:50 +040052 }
53 return ret
54}
55
56func deriveValues(values any, schema Schema, networks []Network) (map[string]any, error) {
57 ret := make(map[string]any)
gio44f621b2024-04-29 09:44:38 +040058 for _, f := range schema.Fields() {
59 k := f.Name
60 def := f.Schema
gio3af43942024-04-16 08:13:50 +040061 // TODO(gio): validate that it is map
62 v, ok := values.(map[string]any)[k]
63 // TODO(gio): if missing use default value
64 if !ok {
65 if def.Kind() == KindSSHKey {
66 key, err := NewECDSASSHKeyPair("tmp")
67 if err != nil {
68 return nil, err
69 }
70 ret[k] = map[string]string{
71 "public": string(key.RawAuthorizedKey()),
72 "private": string(key.RawPrivateKey()),
73 }
74 }
75 continue
76 }
77 switch def.Kind() {
78 case KindBoolean:
79 ret[k] = v
80 case KindString:
81 ret[k] = v
82 case KindInt:
83 ret[k] = v
gioe72b54f2024-04-22 10:44:41 +040084 case KindArrayString:
85 a, ok := v.([]string)
86 if !ok {
87 return nil, fmt.Errorf("expected string array")
88 }
89 ret[k] = a
gio3af43942024-04-16 08:13:50 +040090 case KindNetwork:
91 n, err := findNetwork(networks, v.(string)) // TODO(giolekva): validate
92 if err != nil {
93 return nil, err
94 }
95 ret[k] = n
96 case KindAuth:
97 r, err := deriveValues(v, AuthSchema, networks)
98 if err != nil {
99 return nil, err
100 }
101 ret[k] = r
102 case KindSSHKey:
103 r, err := deriveValues(v, SSHKeySchema, networks)
104 if err != nil {
105 return nil, err
106 }
107 ret[k] = r
108 case KindStruct:
109 r, err := deriveValues(v, def, networks)
110 if err != nil {
111 return nil, err
112 }
113 ret[k] = r
114 default:
115 return nil, fmt.Errorf("Should not reach!")
116 }
117 }
118 return ret, nil
119}
120
121func derivedToConfig(derived map[string]any, schema Schema) (map[string]any, error) {
122 ret := make(map[string]any)
gio44f621b2024-04-29 09:44:38 +0400123 for _, f := range schema.Fields() {
124 k := f.Name
125 def := f.Schema
gio3af43942024-04-16 08:13:50 +0400126 v, ok := derived[k]
127 // TODO(gio): if missing use default value
128 if !ok {
129 continue
130 }
131 switch def.Kind() {
132 case KindBoolean:
133 ret[k] = v
134 case KindString:
135 ret[k] = v
136 case KindInt:
137 ret[k] = v
gioe72b54f2024-04-22 10:44:41 +0400138 case KindArrayString:
139 a, ok := v.([]string)
140 if !ok {
141 return nil, fmt.Errorf("expected string array")
142 }
143 ret[k] = a
gio3af43942024-04-16 08:13:50 +0400144 case KindNetwork:
145 vm, ok := v.(map[string]any)
146 if !ok {
147 return nil, fmt.Errorf("expected map")
148 }
149 name, ok := vm["name"]
150 if !ok {
151 return nil, fmt.Errorf("expected network name")
152 }
153 ret[k] = name
154 case KindAuth:
155 vm, ok := v.(map[string]any)
156 if !ok {
157 return nil, fmt.Errorf("expected map")
158 }
159 r, err := derivedToConfig(vm, AuthSchema)
160 if err != nil {
161 return nil, err
162 }
163 ret[k] = r
164 case KindSSHKey:
165 vm, ok := v.(map[string]any)
166 if !ok {
167 return nil, fmt.Errorf("expected map")
168 }
169 r, err := derivedToConfig(vm, SSHKeySchema)
170 if err != nil {
171 return nil, err
172 }
173 ret[k] = r
174 case KindStruct:
175 vm, ok := v.(map[string]any)
176 if !ok {
177 return nil, fmt.Errorf("expected map")
178 }
179 r, err := derivedToConfig(vm, def)
180 if err != nil {
181 return nil, err
182 }
183 ret[k] = r
184 default:
185 return nil, fmt.Errorf("Should not reach!")
186 }
187 }
188 return ret, nil
189}
190
191func findNetwork(networks []Network, name string) (Network, error) {
192 for _, n := range networks {
193 if n.Name == name {
194 return n, nil
195 }
196 }
197 return Network{}, fmt.Errorf("Network not found: %s", name)
198}