Skip to content

Commit 34d2001

Browse files
Add basic lua script command (#641)
This will allow for locally running lua code against our engine for testing w/o a full deployment. Also supports a separate context file to test sideloaded information that can be added to context.
1 parent 8e500f1 commit 34d2001

10 files changed

Lines changed: 164 additions & 1 deletion

File tree

cmd/command/cd/cd_services.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@ package cd
22

33
import (
44
"fmt"
5+
"path/filepath"
56
"strings"
67

78
"github.com/pluralsh/plural-cli/pkg/common"
9+
lua "github.com/yuin/gopher-lua"
810

911
gqlclient "github.com/pluralsh/console/go/client"
1012
"github.com/pluralsh/plural-cli/pkg/cd/template"
1113
"github.com/pluralsh/plural-cli/pkg/console"
1214
"github.com/pluralsh/plural-cli/pkg/utils"
1315
"github.com/pluralsh/polly/containers"
16+
"github.com/pluralsh/polly/luautils"
1417
"github.com/samber/lo"
1518
"github.com/urfave/cli"
1619
"k8s.io/apimachinery/pkg/util/yaml"
@@ -115,6 +118,25 @@ func (p *Plural) cdServiceCommands() []cli.Command {
115118
},
116119
},
117120
},
121+
{
122+
Name: "lua",
123+
Action: p.handleLuaTemplate,
124+
Usage: "Templates a .lua file using the Plural defined lua engine and returns the result",
125+
Flags: []cli.Flag{
126+
cli.StringFlag{
127+
Name: "lua-file",
128+
Usage: "The .lua file you want to attempt to template.",
129+
},
130+
cli.StringFlag{
131+
Name: "context",
132+
Usage: "A yaml context file to imitate the internal service template context",
133+
},
134+
cli.StringFlag{
135+
Name: "dir",
136+
Usage: "The directory to run the lua script from, defaults to the current working directory",
137+
},
138+
},
139+
},
118140
{
119141
Name: "delete",
120142
ArgsUsage: "@{cluster-handle}/{serviceName}",
@@ -277,6 +299,77 @@ func (p *Plural) handleTemplateService(c *cli.Context) error {
277299
return printResult(res)
278300
}
279301

302+
func (p *Plural) handleLuaTemplate(c *cli.Context) error {
303+
if err := p.InitConsoleClient(consoleToken, consoleURL); err != nil {
304+
return err
305+
}
306+
307+
luaFile := c.String("lua-file")
308+
context := c.String("context")
309+
dir := c.String("dir")
310+
if dir == "" {
311+
dir = "."
312+
}
313+
314+
if luaFile == "" {
315+
return fmt.Errorf("expected --lua-file flag")
316+
}
317+
318+
luaStr, err := utils.ReadFile(luaFile)
319+
if err != nil {
320+
return err
321+
}
322+
323+
ctx := map[string]interface{}{}
324+
if context != "" {
325+
if err := utils.YamlFile(context, &ctx); err != nil {
326+
return err
327+
}
328+
}
329+
330+
values := map[interface{}]interface{}{}
331+
valuesFiles := []string{}
332+
333+
dir, err = filepath.Abs(dir)
334+
if err != nil {
335+
return err
336+
}
337+
proc := luautils.NewProcessor(dir)
338+
defer proc.L.Close()
339+
340+
// Register global values and valuesFiles in Lua
341+
valuesTable := proc.L.NewTable()
342+
proc.L.SetGlobal("values", valuesTable)
343+
344+
valuesFilesTable := proc.L.NewTable()
345+
proc.L.SetGlobal("valuesFiles", valuesFilesTable)
346+
proc.L.SetGlobal("cluster", luautils.GoValueToLuaValue(proc.L, ctx["cluster"]))
347+
proc.L.SetGlobal("configuration", luautils.GoValueToLuaValue(proc.L, ctx["configuration"]))
348+
proc.L.SetGlobal("contexts", luautils.GoValueToLuaValue(proc.L, ctx["contexts"]))
349+
proc.L.SetGlobal("imports", luautils.GoValueToLuaValue(proc.L, ctx["imports"]))
350+
351+
if err := proc.L.DoString(luaStr); err != nil {
352+
return err
353+
}
354+
355+
if err := luautils.MapLua(proc.L.GetGlobal("values").(*lua.LTable), &values); err != nil {
356+
return err
357+
}
358+
359+
if err := luautils.MapLua(proc.L.GetGlobal("valuesFiles").(*lua.LTable), &valuesFiles); err != nil {
360+
return err
361+
}
362+
363+
result := map[string]interface{}{
364+
"values": luautils.SanitizeValue(values),
365+
"valuesFiles": valuesFiles,
366+
}
367+
368+
utils.Highlight("Final lua output:\n\n")
369+
utils.NewYAMLPrinter(result).PrettyPrint()
370+
return nil
371+
}
372+
280373
func (p *Plural) handleCloneClusterService(c *cli.Context) error {
281374
if err := p.InitConsoleClient(consoleToken, consoleURL); err != nil {
282375
return err

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ require (
4141
github.com/pluralsh/console/go/controller v0.0.0-20250430123026-a75a764f035b
4242
github.com/pluralsh/gqlclient v1.12.2
4343
github.com/pluralsh/plural-operator v0.5.5
44-
github.com/pluralsh/polly v0.2.0
44+
github.com/pluralsh/polly v0.2.7
4545
github.com/posthog/posthog-go v1.4.10
4646
github.com/samber/lo v1.50.0
4747
github.com/urfave/cli v1.22.16

go.sum

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,14 @@ github.com/pluralsh/plural-operator v0.5.5 h1:57GxniNjUa3hpHgvFr9oDonFgvDUC8XDD5
724724
github.com/pluralsh/plural-operator v0.5.5/go.mod h1:WIXiz26/WDcUn0FA7Q1jPxmfsm98U1/JL8YpIdKVLX0=
725725
github.com/pluralsh/polly v0.2.0 h1:i0Yu13Lwef9u7hyiqHLyDZhkT1G1uXcaK6Ph7EeXjxo=
726726
github.com/pluralsh/polly v0.2.0/go.mod h1:o+oi+FXNThipKNyZsqCemqwY0JdkvhEjQqi8aTw8l4M=
727+
github.com/pluralsh/polly v0.2.4 h1:OyxUq324sTE/ZM5AVUZAgeZCLxM77gfqlB6uIOGihFo=
728+
github.com/pluralsh/polly v0.2.4/go.mod h1:GpeJrbPW0XedsoTXYRPhS5mc6GqIYLocOaRRSsZGisQ=
729+
github.com/pluralsh/polly v0.2.5 h1:JO6rqZChuV+SQ4xry07XctZDW3DqYaWqEWsrio8k88A=
730+
github.com/pluralsh/polly v0.2.5/go.mod h1:GpeJrbPW0XedsoTXYRPhS5mc6GqIYLocOaRRSsZGisQ=
731+
github.com/pluralsh/polly v0.2.6 h1:BS2ubNJoXM2HwVEJxcgpew/j9ErYEzk91ArkqUavr5w=
732+
github.com/pluralsh/polly v0.2.6/go.mod h1:GpeJrbPW0XedsoTXYRPhS5mc6GqIYLocOaRRSsZGisQ=
733+
github.com/pluralsh/polly v0.2.7 h1:Sk0rW9jGH82jdCFGpz2B8X4qz+LcBxadl2ToUFoS9Q0=
734+
github.com/pluralsh/polly v0.2.7/go.mod h1:GpeJrbPW0XedsoTXYRPhS5mc6GqIYLocOaRRSsZGisQ=
727735
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
728736
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
729737
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=

test/lua/basic.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
values = {}
2+
valuesFiles = {}
3+
local parts = {"a", "b", "c"}
4+
local joined = utils.pathJoin(parts)
5+
values["joined"] = joined

test/lua/fleeta/cluster.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
spec:
2+
region: us-east-1
3+
nodes:
4+
- name: node1
5+
type: t3.small
6+
count: 1
7+
- name: node2
8+
type: t3.small
9+
count: 1
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
cluster: dev-cluster-a
2+
spec: {}

test/lua/fleeta/dev/cluster.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
spec:
2+
region: us-east-2
3+
nodes:
4+
- name: node1
5+
type: t3.small
6+
count: 1
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
cluster: prod-cluster-a
2+
spec: {}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
cluster: prod-cluster-b
2+
spec: {}

test/lua/fsmerge.lua

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
values = {}
2+
valuesFiles = {}
3+
4+
files, err = fs.walk("test/lua/fleeta")
5+
if err then
6+
error(err)
7+
return
8+
end
9+
10+
table.sort(files, function(a, b)
11+
local aParts = utils.splitString(a, "/")
12+
local bParts = utils.splitString(b, "/")
13+
return #aParts < #bParts
14+
end)
15+
16+
local workset = {}
17+
18+
for _, file in ipairs(files) do
19+
local f = fs.read(file)
20+
local asYaml = encoding.yamlDecode(f)
21+
local parent = {}
22+
local parts = utils.splitString(file, "/")
23+
local i = #parts - 1
24+
while i > 0 do
25+
local parentFile = table.concat(parts, "/", 1, i - 1) .. "/cluster.yaml"
26+
if workset[parentFile] then
27+
parent = workset[parentFile]
28+
break
29+
end
30+
i = i - 1
31+
end
32+
workset[file] = utils.merge(parent, asYaml)
33+
if workset[file].cluster then
34+
values[workset[file].cluster] = workset[file]
35+
end
36+
end

0 commit comments

Comments
 (0)