blob: fcf39ffcec9d148e3ed412556e69ae3f17c3d3a2 [file] [log] [blame]
giolekva8aa73e82022-07-09 11:34:39 +04001package installer
giolekva050609f2021-12-29 15:51:40 +04002
giolekva8aa73e82022-07-09 11:34:39 +04003import (
Giorgi Lekveishvili3f697b12024-01-04 00:56:06 +04004 "bytes"
Giorgi Lekveishvili9b52ab92024-01-05 13:12:48 +04005 "encoding/json"
Giorgi Lekveishvilibd6be7f2023-05-26 15:51:28 +04006 "fmt"
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +04007 template "html/template"
gio3cdee592024-04-17 10:15:56 +04008 "net"
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +04009 "strings"
Giorgi Lekveishvili0ccd1482023-06-21 15:02:24 +040010
Giorgi Lekveishvili9b52ab92024-01-05 13:12:48 +040011 "cuelang.org/go/cue"
gio308105e2024-04-19 13:12:13 +040012 "cuelang.org/go/cue/build"
13 "cuelang.org/go/cue/cuecontext"
14 "cuelang.org/go/cue/load"
Giorgi Lekveishvili9b52ab92024-01-05 13:12:48 +040015 cueyaml "cuelang.org/go/encoding/yaml"
giolekva8aa73e82022-07-09 11:34:39 +040016)
giolekva050609f2021-12-29 15:51:40 +040017
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +040018// TODO(gio): import
19const cueBaseConfig = `
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +040020name: string | *""
21description: string | *""
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +040022readme: string | *""
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +040023icon: string | *""
24namespace: string | *""
Davit Tabidze56f86a42024-04-09 19:15:25 +040025help: [...#HelpDocument] | *[]
26
27#HelpDocument: {
28 title: string
29 contents: string
30 children: [...#HelpDocument] | *[]
31}
32
33url: string | *""
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +040034
gio308105e2024-04-19 13:12:13 +040035#AppType: "infra" | "env"
36appType: #AppType | *"env"
37
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +040038#Auth: {
39 enabled: bool | *false // TODO(gio): enabled by default?
40 groups: string | *"" // TODO(gio): []string
41}
42
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +040043#Network: {
44 name: string
45 ingressClass: string
46 certificateIssuer: string | *""
47 domain: string
Giorgi Lekveishvilib59b7c22024-04-03 22:17:50 +040048 allocatePortAddr: string
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +040049}
50
Giorgi Lekveishvili67383962024-03-22 19:27:34 +040051networks: {
52 public: #Network & {
53 name: "Public"
54 ingressClass: "\(global.pcloudEnvName)-ingress-public"
55 certificateIssuer: "\(global.id)-public"
56 domain: global.domain
Giorgi Lekveishvilib59b7c22024-04-03 22:17:50 +040057 allocatePortAddr: "http://port-allocator.\(global.pcloudEnvName)-ingress-public.svc.cluster.local/api/allocate"
Giorgi Lekveishvili67383962024-03-22 19:27:34 +040058 }
59 private: #Network & {
60 name: "Private"
61 ingressClass: "\(global.id)-ingress-private"
62 domain: global.privateDomain
Giorgi Lekveishvilib59b7c22024-04-03 22:17:50 +040063 allocatePortAddr: "http://port-allocator.\(global.id)-ingress-private.svc.cluster.local/api/allocate"
Giorgi Lekveishvili67383962024-03-22 19:27:34 +040064 }
65}
66
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +040067#Image: {
68 registry: string | *"docker.io"
69 repository: string
70 name: string
71 tag: string
72 pullPolicy: string | *"IfNotPresent"
73 imageName: "\(repository)/\(name)"
74 fullName: "\(registry)/\(imageName)"
75 fullNameWithTag: "\(fullName):\(tag)"
76}
77
78#Chart: {
79 chart: string
80 sourceRef: #SourceRef
81}
82
83#SourceRef: {
84 kind: "GitRepository" | "HelmRepository"
85 name: string
86 namespace: string // TODO(gio): default global.id
87}
88
89#Global: {
90 id: string | *""
91 pcloudEnvName: string | *""
92 domain: string | *""
93 privateDomain: string | *""
94 namespacePrefix: string | *""
95 ...
96}
97
98#Release: {
gio3cdee592024-04-17 10:15:56 +040099 appInstanceId: string
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400100 namespace: string
Giorgi Lekveishvilib59b7c22024-04-03 22:17:50 +0400101 repoAddr: string
102 appDir: string
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400103}
104
Giorgi Lekveishvilib59b7c22024-04-03 22:17:50 +0400105#PortForward: {
106 allocator: string
107 protocol: "TCP" | "UDP" | *"TCP"
108 sourcePort: int
109 targetService: string
110 targetPort: int
111}
112
113portForward: [...#PortForward] | *[]
114
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400115global: #Global
116release: #Release
117
118_ingressPrivate: "\(global.id)-ingress-private"
119_ingressPublic: "\(global.pcloudEnvName)-ingress-public"
120_issuerPrivate: "\(global.id)-private"
121_issuerPublic: "\(global.id)-public"
122
gio1de49582024-04-21 08:33:57 +0400123#Ingress: {
124 auth: #Auth
125 network: #Network
126 subdomain: string
127 service: close({
128 name: string
129 port: close({ name: string }) | close({ number: int & > 0 })
130 })
Giorgi Lekveishvili67383962024-03-22 19:27:34 +0400131
gio1de49582024-04-21 08:33:57 +0400132 _domain: "\(subdomain).\(network.domain)"
Giorgi Lekveishvili67383962024-03-22 19:27:34 +0400133 _authProxyHTTPPortName: "http"
134
135 out: {
136 images: {
137 authProxy: #Image & {
138 repository: "giolekva"
139 name: "auth-proxy"
140 tag: "latest"
141 pullPolicy: "Always"
142 }
143 }
144 charts: {
145 ingress: #Chart & {
146 chart: "charts/ingress"
147 sourceRef: {
148 kind: "GitRepository"
149 name: "pcloud"
150 namespace: global.id
151 }
152 }
153 authProxy: #Chart & {
154 chart: "charts/auth-proxy"
155 sourceRef: {
156 kind: "GitRepository"
157 name: "pcloud"
158 namespace: global.id
159 }
160 }
161 }
162 helm: {
gio1de49582024-04-21 08:33:57 +0400163 if auth.enabled {
Giorgi Lekveishvili67383962024-03-22 19:27:34 +0400164 "auth-proxy": {
165 chart: charts.authProxy
166 values: {
167 image: {
168 repository: images.authProxy.fullName
169 tag: images.authProxy.tag
170 pullPolicy: images.authProxy.pullPolicy
171 }
gio1de49582024-04-21 08:33:57 +0400172 upstream: "\(service.name).\(release.namespace).svc.cluster.local"
Giorgi Lekveishvili67383962024-03-22 19:27:34 +0400173 whoAmIAddr: "https://accounts.\(global.domain)/sessions/whoami"
174 loginAddr: "https://accounts-ui.\(global.domain)/login"
Giorgi Lekveishvili329af572024-03-25 20:14:41 +0400175 membershipAddr: "http://memberships-api.\(global.id)-core-auth-memberships.svc.cluster.local/api/user"
gio1de49582024-04-21 08:33:57 +0400176 groups: auth.groups
Giorgi Lekveishvili67383962024-03-22 19:27:34 +0400177 portName: _authProxyHTTPPortName
178 }
179 }
180 }
181 ingress: {
182 chart: charts.ingress
gio1de49582024-04-21 08:33:57 +0400183 _service: service
Giorgi Lekveishvili67383962024-03-22 19:27:34 +0400184 values: {
185 domain: _domain
gio1de49582024-04-21 08:33:57 +0400186 ingressClassName: network.ingressClass
187 certificateIssuer: network.certificateIssuer
Giorgi Lekveishvili67383962024-03-22 19:27:34 +0400188 service: {
gio1de49582024-04-21 08:33:57 +0400189 if auth.enabled {
Giorgi Lekveishvili67383962024-03-22 19:27:34 +0400190 name: "auth-proxy"
191 port: name: _authProxyHTTPPortName
192 }
gio1de49582024-04-21 08:33:57 +0400193 if !auth.enabled {
194 name: _service.name
195 if _service.port.name != _|_ {
196 port: name: _service.port.name
Giorgi Lekveishvili67383962024-03-22 19:27:34 +0400197 }
gio1de49582024-04-21 08:33:57 +0400198 if _service.port.number != _|_ {
199 port: number: _service.port.number
Giorgi Lekveishvili67383962024-03-22 19:27:34 +0400200 }
201 }
202 }
203 }
204 }
205 }
206 }
207}
208
gio1de49582024-04-21 08:33:57 +0400209ingress: {}
210
211_ingressValidate: {
212 for key, value in ingress {
213 "\(key)": #Ingress & value
214 }
215}
216
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400217images: {
218 for key, value in images {
219 "\(key)": #Image & value
220 }
gio1de49582024-04-21 08:33:57 +0400221 for _, value in _ingressValidate {
222 for name, image in value.out.images {
223 "\(name)": #Image & image
224 }
225 }
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400226}
227
228charts: {
229 for key, value in charts {
230 "\(key)": #Chart & value
231 }
gio1de49582024-04-21 08:33:57 +0400232 for _, value in _ingressValidate {
233 for name, chart in value.out.charts {
234 "\(name)": #Chart & chart
235 }
236 }
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400237}
238
239#ResourceReference: {
240 name: string
241 namespace: string
242}
243
244#Helm: {
245 name: string
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +0400246 dependsOn: [...#ResourceReference] | *[]
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400247 ...
248}
249
gio1de49582024-04-21 08:33:57 +0400250_helmValidate: {
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400251 for key, value in helm {
252 "\(key)": #Helm & value & {
253 name: key
254 }
255 }
gio1de49582024-04-21 08:33:57 +0400256 for key, value in _ingressValidate {
257 for ing, ingValue in value.out.helm {
258 // TODO(gio): support multiple ingresses
259 // "\(key)-\(ing)": #Helm & ingValue & {
260 "\(ing)": #Helm & ingValue & {
261 // name: "\(key)-\(ing)"
262 name: ing
263 }
264 }
265 }
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400266}
267
268#HelmRelease: {
269 _name: string
270 _chart: #Chart
271 _values: _
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +0400272 _dependencies: [...#ResourceReference] | *[]
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400273
274 apiVersion: "helm.toolkit.fluxcd.io/v2beta1"
275 kind: "HelmRelease"
276 metadata: {
277 name: _name
278 namespace: release.namespace
279 }
280 spec: {
281 interval: "1m0s"
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +0400282 dependsOn: _dependencies
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400283 chart: {
284 spec: _chart
285 }
286 values: _values
287 }
288}
289
290output: {
gio1de49582024-04-21 08:33:57 +0400291 for name, r in _helmValidate {
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400292 "\(name)": #HelmRelease & {
293 _name: name
294 _chart: r.chart
295 _values: r.values
296 _dependencies: r.dependsOn
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400297 }
298 }
299}
Giorgi Lekveishvilib6a58062024-04-02 16:49:19 +0400300
301#SSHKey: {
302 public: string
303 private: string
304}
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400305`
306
Giorgi Lekveishvili9b52ab92024-01-05 13:12:48 +0400307type Rendered struct {
gio3cdee592024-04-17 10:15:56 +0400308 Name string
Giorgi Lekveishvili9b52ab92024-01-05 13:12:48 +0400309 Readme string
gio308105e2024-04-19 13:12:13 +0400310 Resources CueAppData
Giorgi Lekveishvilib59b7c22024-04-03 22:17:50 +0400311 Ports []PortForward
gio3cdee592024-04-17 10:15:56 +0400312 Config AppInstanceConfig
gio308105e2024-04-19 13:12:13 +0400313 Data CueAppData
Davit Tabidze56f86a42024-04-09 19:15:25 +0400314 Help []HelpDocument
315 Url string
316 Icon string
317}
318
319type HelpDocument struct {
320 Title string
321 Contents string
322 Children []HelpDocument
Giorgi Lekveishvili9b52ab92024-01-05 13:12:48 +0400323}
324
gio3cdee592024-04-17 10:15:56 +0400325type PortForward struct {
326 Allocator string `json:"allocator"`
327 Protocol string `json:"protocol"`
328 SourcePort int `json:"sourcePort"`
329 TargetService string `json:"targetService"`
330 TargetPort int `json:"targetPort"`
331}
332
333type AppType int
334
335const (
336 AppTypeInfra AppType = iota
337 AppTypeEnv
338)
339
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +0400340type App interface {
gio3cdee592024-04-17 10:15:56 +0400341 Type() AppType
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +0400342 Name() string
343 Description() string
344 Icon() template.HTML
345 Schema() Schema
gioef01fbb2024-04-12 16:52:59 +0400346 Namespace() string
gio3cdee592024-04-17 10:15:56 +0400347}
348
349type InfraConfig struct {
350 Name string `json:"pcloudEnvName"` // #TODO(gio): change to name
351 PublicIP []net.IP `json:"publicIP"`
352 InfraNamespacePrefix string `json:"namespacePrefix"`
353 InfraAdminPublicKey []byte `json:"infraAdminPublicKey"`
354}
355
356type InfraApp interface {
357 App
358 Render(release Release, infra InfraConfig, values map[string]any) (Rendered, error)
359}
360
361// TODO(gio): rename to EnvConfig
362type AppEnvConfig struct {
363 Id string `json:"id"`
364 InfraName string `json:"pcloudEnvName"`
365 Domain string `json:"domain"`
366 PrivateDomain string `json:"privateDomain"`
367 ContactEmail string `json:"contactEmail"`
368 PublicIP []net.IP `json:"publicIP"`
369 NamespacePrefix string `json:"namespacePrefix"`
370}
371
372type EnvApp interface {
373 App
374 Render(release Release, env AppEnvConfig, values map[string]any) (Rendered, error)
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400375}
376
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +0400377type cueApp struct {
378 name string
379 description string
380 icon template.HTML
381 namespace string
382 schema Schema
gio308105e2024-04-19 13:12:13 +0400383 cfg cue.Value
384 data CueAppData
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +0400385}
386
gio308105e2024-04-19 13:12:13 +0400387type CueAppData map[string][]byte
388
389func ParseCueAppConfig(data CueAppData) (cue.Value, error) {
390 ctx := cuecontext.New()
391 buildCtx := build.NewContext()
392 cfg := &load.Config{
393 Context: buildCtx,
394 Overlay: map[string]load.Source{},
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +0400395 }
gio308105e2024-04-19 13:12:13 +0400396 names := make([]string, 0)
397 for n, b := range data {
398 a := fmt.Sprintf("/%s", n)
399 names = append(names, a)
400 cfg.Overlay[a] = load.FromString("package main\n\n" + string(b))
401 }
402 instances := load.Instances(names, cfg)
403 for _, inst := range instances {
404 if inst.Err != nil {
405 return cue.Value{}, inst.Err
406 }
407 }
408 if len(instances) != 1 {
409 return cue.Value{}, fmt.Errorf("invalid")
410 }
411 ret := ctx.BuildInstance(instances[0])
412 if ret.Err() != nil {
413 return cue.Value{}, ret.Err()
414 }
415 if err := ret.Validate(); err != nil {
416 return cue.Value{}, err
417 }
418 return ret, nil
419}
420
421func newCueApp(config cue.Value, data CueAppData) (cueApp, error) {
gio3cdee592024-04-17 10:15:56 +0400422 cfg := struct {
423 Name string `json:"name"`
424 Namespace string `json:"namespace"`
425 Description string `json:"description"`
426 Icon string `json:"icon"`
427 }{}
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +0400428 if err := config.Decode(&cfg); err != nil {
429 return cueApp{}, err
430 }
431 schema, err := NewCueSchema(config.LookupPath(cue.ParsePath("input")))
432 if err != nil {
433 return cueApp{}, err
434 }
435 return cueApp{
436 name: cfg.Name,
437 description: cfg.Description,
438 icon: template.HTML(cfg.Icon),
439 namespace: cfg.Namespace,
440 schema: schema,
441 cfg: config,
gio308105e2024-04-19 13:12:13 +0400442 data: data,
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +0400443 }, nil
444}
445
gio308105e2024-04-19 13:12:13 +0400446func ParseAndCreateNewCueApp(data CueAppData) (cueApp, error) {
447 config, err := ParseCueAppConfig(data)
448 if err != nil {
449 return cueApp{}, err
450 }
451 return newCueApp(config, data)
452}
453
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +0400454func (a cueApp) Name() string {
455 return a.name
456}
457
458func (a cueApp) Description() string {
459 return a.description
460}
461
462func (a cueApp) Icon() template.HTML {
463 return a.icon
464}
465
466func (a cueApp) Schema() Schema {
467 return a.schema
468}
469
gioef01fbb2024-04-12 16:52:59 +0400470func (a cueApp) Namespace() string {
471 return a.namespace
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +0400472}
473
gio3cdee592024-04-17 10:15:56 +0400474func (a cueApp) render(values map[string]any) (Rendered, error) {
Giorgi Lekveishvili9b52ab92024-01-05 13:12:48 +0400475 ret := Rendered{
gio3cdee592024-04-17 10:15:56 +0400476 Name: a.Name(),
gio308105e2024-04-19 13:12:13 +0400477 Resources: make(CueAppData),
Giorgi Lekveishvilib59b7c22024-04-03 22:17:50 +0400478 Ports: make([]PortForward, 0),
gio308105e2024-04-19 13:12:13 +0400479 Data: a.data,
Giorgi Lekveishvili9b52ab92024-01-05 13:12:48 +0400480 }
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +0400481 var buf bytes.Buffer
gio3cdee592024-04-17 10:15:56 +0400482 if err := json.NewEncoder(&buf).Encode(values); err != nil {
Giorgi Lekveishvili9b52ab92024-01-05 13:12:48 +0400483 return Rendered{}, err
484 }
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +0400485 ctx := a.cfg.Context()
486 d := ctx.CompileBytes(buf.Bytes())
487 res := a.cfg.Unify(d).Eval()
488 if err := res.Err(); err != nil {
489 return Rendered{}, err
490 }
491 if err := res.Validate(); err != nil {
492 return Rendered{}, err
493 }
gio308105e2024-04-19 13:12:13 +0400494 full, err := json.MarshalIndent(res, "", "\t")
495 if err != nil {
496 return Rendered{}, err
497 }
498 ret.Data["rendered.json"] = full
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +0400499 readme, err := res.LookupPath(cue.ParsePath("readme")).String()
500 if err != nil {
501 return Rendered{}, err
502 }
503 ret.Readme = readme
Giorgi Lekveishvilib59b7c22024-04-03 22:17:50 +0400504 if err := res.LookupPath(cue.ParsePath("portForward")).Decode(&ret.Ports); err != nil {
505 return Rendered{}, err
506 }
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +0400507 output := res.LookupPath(cue.ParsePath("output"))
508 i, err := output.Fields()
509 if err != nil {
510 return Rendered{}, err
511 }
512 for i.Next() {
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +0400513 if contents, err := cueyaml.Encode(i.Value()); err != nil {
Giorgi Lekveishvili9b52ab92024-01-05 13:12:48 +0400514 return Rendered{}, err
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +0400515 } else {
516 name := fmt.Sprintf("%s.yaml", cleanName(i.Selector().String()))
517 ret.Resources[name] = contents
Giorgi Lekveishvili3f697b12024-01-04 00:56:06 +0400518 }
Giorgi Lekveishvili3f697b12024-01-04 00:56:06 +0400519 }
Davit Tabidze56f86a42024-04-09 19:15:25 +0400520 helpValue := res.LookupPath(cue.ParsePath("help"))
521 if helpValue.Exists() {
522 if err := helpValue.Decode(&ret.Help); err != nil {
523 return Rendered{}, err
524 }
525 }
526 url, err := res.LookupPath(cue.ParsePath("url")).String()
527 if err != nil {
528 return Rendered{}, err
529 }
530 ret.Url = url
531 icon, err := res.LookupPath(cue.ParsePath("icon")).String()
532 if err != nil {
533 return Rendered{}, err
534 }
535 ret.Icon = icon
Giorgi Lekveishvili3f697b12024-01-04 00:56:06 +0400536 return ret, nil
537}
538
gio3cdee592024-04-17 10:15:56 +0400539type cueEnvApp struct {
540 cueApp
Giorgi Lekveishvilibd6be7f2023-05-26 15:51:28 +0400541}
542
gio308105e2024-04-19 13:12:13 +0400543func NewCueEnvApp(data CueAppData) (EnvApp, error) {
544 app, err := ParseAndCreateNewCueApp(data)
Giorgi Lekveishvili743fb432023-11-08 17:19:40 +0400545 if err != nil {
546 return nil, err
547 }
gio3cdee592024-04-17 10:15:56 +0400548 return cueEnvApp{app}, nil
Giorgi Lekveishvili743fb432023-11-08 17:19:40 +0400549}
550
gio3cdee592024-04-17 10:15:56 +0400551func (a cueEnvApp) Type() AppType {
552 return AppTypeEnv
553}
554
555func (a cueEnvApp) Render(release Release, env AppEnvConfig, values map[string]any) (Rendered, error) {
556 networks := CreateNetworks(env)
557 derived, err := deriveValues(values, a.Schema(), networks)
558 if err != nil {
559 return Rendered{}, nil
560 }
561 ret, err := a.cueApp.render(map[string]any{
562 "global": env,
563 "release": release,
564 "input": derived,
565 })
566 if err != nil {
567 return Rendered{}, err
568 }
569 ret.Config = AppInstanceConfig{
570 AppId: a.Name(),
571 Env: env,
572 Release: release,
573 Values: values,
574 Input: derived,
Davit Tabidze56f86a42024-04-09 19:15:25 +0400575 Help: ret.Help,
576 Url: ret.Url,
gio3cdee592024-04-17 10:15:56 +0400577 }
578 return ret, nil
579}
580
581type cueInfraApp struct {
582 cueApp
583}
584
gio308105e2024-04-19 13:12:13 +0400585func NewCueInfraApp(data CueAppData) (InfraApp, error) {
586 app, err := ParseAndCreateNewCueApp(data)
Giorgi Lekveishvili743fb432023-11-08 17:19:40 +0400587 if err != nil {
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +0400588 return nil, err
Giorgi Lekveishvili743fb432023-11-08 17:19:40 +0400589 }
gio3cdee592024-04-17 10:15:56 +0400590 return cueInfraApp{app}, nil
591}
592
593func (a cueInfraApp) Type() AppType {
594 return AppTypeInfra
595}
596
597func (a cueInfraApp) Render(release Release, infra InfraConfig, values map[string]any) (Rendered, error) {
598 return a.cueApp.render(map[string]any{
599 "global": infra,
600 "release": release,
601 "input": values,
602 })
Giorgi Lekveishvilief21c132024-01-17 18:57:58 +0400603}
604
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +0400605func cleanName(s string) string {
606 return strings.ReplaceAll(strings.ReplaceAll(s, "\"", ""), "'", "")
Giorgi Lekveishvilief21c132024-01-17 18:57:58 +0400607}