blob: c3483cf9fe99c631fa371eda57d1d4d8fd818392 [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"`
gio3af43942024-04-16 08:13:50 +040013}
14
15type Network struct {
16 Name string `json:"name,omitempty"`
17 IngressClass string `json:"ingressClass,omitempty"`
18 CertificateIssuer string `json:"certificateIssuer,omitempty"`
19 Domain string `json:"domain,omitempty"`
20 AllocatePortAddr string `json:"allocatePortAddr,omitempty"`
21}
22
gioe72b54f2024-04-22 10:44:41 +040023type InfraAppInstanceConfig struct {
24 Id string `json:"id"`
25 AppId string `json:"appId"`
26 Infra InfraConfig `json:"infra"`
27 Release Release `json:"release"`
28 Values map[string]any `json:"values"`
29 Input map[string]any `json:"input"`
gio09a3e5b2024-04-26 14:11:06 +040030 URL string `json:"url"`
31 Help []HelpDocument `json:"help"`
32 Icon template.HTML `json:"icon"`
gioe72b54f2024-04-22 10:44:41 +040033}
34
gio3cdee592024-04-17 10:15:56 +040035type AppInstanceConfig struct {
gio3af43942024-04-16 08:13:50 +040036 Id string `json:"id"`
37 AppId string `json:"appId"`
gioe72b54f2024-04-22 10:44:41 +040038 Env EnvConfig `json:"env"`
gio3cdee592024-04-17 10:15:56 +040039 Release Release `json:"release"`
40 Values map[string]any `json:"values"`
41 Input map[string]any `json:"input"`
gio09a3e5b2024-04-26 14:11:06 +040042 URL string `json:"url"`
Davit Tabidze56f86a42024-04-09 19:15:25 +040043 Help []HelpDocument `json:"help"`
gio09a3e5b2024-04-26 14:11:06 +040044 Icon string `json:"icon"`
gio3af43942024-04-16 08:13:50 +040045}
46
gio3cdee592024-04-17 10:15:56 +040047func (a AppInstanceConfig) InputToValues(schema Schema) map[string]any {
48 ret, err := derivedToConfig(a.Input, schema)
gio3af43942024-04-16 08:13:50 +040049 if err != nil {
gio3cdee592024-04-17 10:15:56 +040050 panic(err)
gio3af43942024-04-16 08:13:50 +040051 }
52 return ret
53}
54
55func deriveValues(values any, schema Schema, networks []Network) (map[string]any, error) {
56 ret := make(map[string]any)
gio44f621b2024-04-29 09:44:38 +040057 for _, f := range schema.Fields() {
58 k := f.Name
59 def := f.Schema
gio3af43942024-04-16 08:13:50 +040060 // TODO(gio): validate that it is map
61 v, ok := values.(map[string]any)[k]
62 // TODO(gio): if missing use default value
63 if !ok {
64 if def.Kind() == KindSSHKey {
65 key, err := NewECDSASSHKeyPair("tmp")
66 if err != nil {
67 return nil, err
68 }
69 ret[k] = map[string]string{
70 "public": string(key.RawAuthorizedKey()),
71 "private": string(key.RawPrivateKey()),
72 }
73 }
74 continue
75 }
76 switch def.Kind() {
77 case KindBoolean:
78 ret[k] = v
79 case KindString:
80 ret[k] = v
81 case KindInt:
82 ret[k] = v
gioe72b54f2024-04-22 10:44:41 +040083 case KindArrayString:
84 a, ok := v.([]string)
85 if !ok {
86 return nil, fmt.Errorf("expected string array")
87 }
88 ret[k] = a
gio3af43942024-04-16 08:13:50 +040089 case KindNetwork:
90 n, err := findNetwork(networks, v.(string)) // TODO(giolekva): validate
91 if err != nil {
92 return nil, err
93 }
94 ret[k] = n
95 case KindAuth:
96 r, err := deriveValues(v, AuthSchema, networks)
97 if err != nil {
98 return nil, err
99 }
100 ret[k] = r
101 case KindSSHKey:
102 r, err := deriveValues(v, SSHKeySchema, networks)
103 if err != nil {
104 return nil, err
105 }
106 ret[k] = r
107 case KindStruct:
108 r, err := deriveValues(v, def, networks)
109 if err != nil {
110 return nil, err
111 }
112 ret[k] = r
113 default:
114 return nil, fmt.Errorf("Should not reach!")
115 }
116 }
117 return ret, nil
118}
119
120func derivedToConfig(derived map[string]any, schema Schema) (map[string]any, error) {
121 ret := make(map[string]any)
gio44f621b2024-04-29 09:44:38 +0400122 for _, f := range schema.Fields() {
123 k := f.Name
124 def := f.Schema
gio3af43942024-04-16 08:13:50 +0400125 v, ok := derived[k]
126 // TODO(gio): if missing use default value
127 if !ok {
128 continue
129 }
130 switch def.Kind() {
131 case KindBoolean:
132 ret[k] = v
133 case KindString:
134 ret[k] = v
135 case KindInt:
136 ret[k] = v
gioe72b54f2024-04-22 10:44:41 +0400137 case KindArrayString:
138 a, ok := v.([]string)
139 if !ok {
140 return nil, fmt.Errorf("expected string array")
141 }
142 ret[k] = a
gio3af43942024-04-16 08:13:50 +0400143 case KindNetwork:
144 vm, ok := v.(map[string]any)
145 if !ok {
146 return nil, fmt.Errorf("expected map")
147 }
148 name, ok := vm["name"]
149 if !ok {
150 return nil, fmt.Errorf("expected network name")
151 }
152 ret[k] = name
153 case KindAuth:
154 vm, ok := v.(map[string]any)
155 if !ok {
156 return nil, fmt.Errorf("expected map")
157 }
158 r, err := derivedToConfig(vm, AuthSchema)
159 if err != nil {
160 return nil, err
161 }
162 ret[k] = r
163 case KindSSHKey:
164 vm, ok := v.(map[string]any)
165 if !ok {
166 return nil, fmt.Errorf("expected map")
167 }
168 r, err := derivedToConfig(vm, SSHKeySchema)
169 if err != nil {
170 return nil, err
171 }
172 ret[k] = r
173 case KindStruct:
174 vm, ok := v.(map[string]any)
175 if !ok {
176 return nil, fmt.Errorf("expected map")
177 }
178 r, err := derivedToConfig(vm, def)
179 if err != nil {
180 return nil, err
181 }
182 ret[k] = r
183 default:
184 return nil, fmt.Errorf("Should not reach!")
185 }
186 }
187 return ret, nil
188}
189
190func findNetwork(networks []Network, name string) (Network, error) {
191 for _, n := range networks {
192 if n.Name == name {
193 return n, nil
194 }
195 }
196 return Network{}, fmt.Errorf("Network not found: %s", name)
197}