Skip to content

Commit 52e3c38

Browse files
Refactor script running & add subscript capabilities (#24)
* move script/task logic to script object so it can easily be reused * add support for sub-scripts * documentation updates for scripts * don't use log.Default to keep 1.15 compat; upgrade circleci container
1 parent b3dfa21 commit 52e3c38

File tree

13 files changed

+328
-132
lines changed

13 files changed

+328
-132
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ jobs:
44
build:
55
working_directory: ~/repo
66
docker:
7-
- image: circleci/golang:1.15.8
7+
- image: circleci/golang:1.15.15
88
steps:
99
- checkout
1010
- restore_cache:

README.md

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Uinit is a simple golang init process that is intended to be run from within u-root (but can run elsewhere too, say, as a light-weight container init).
44

5-
# Overview
5+
## Overview
66

77
Uinit is built to be *scriptable* with a simple YAML-format file. For an example script, see: [cmds/uinit/uinit.script](cmds/uinit/uinit.script).
88

@@ -17,19 +17,39 @@ Uinit reads the script as a sequence of tasks. Each task calls a "module", and
1717
- setvar : Sets a variable in the key/value store that can be later referenced.
1818
- cmdline : Reads a file containing commandline arguments of the style: `uinit.<key>=<val>` adn sets `<key> = <val>` in the key/value store. If formated as `uinit.key`, then `val="true"` implicitly. This is intended primarily to read variables from `/proc/cmdline` which is the default file to parse, allowing for uinit configuration by kernel parameters. The prefix, which defaults to `uinit` can be set to anything.
1919
- mount : Mount a filesystem.
20+
- script : Run a subscript, either directly specified or in another script file.
2021

2122
More modules to come! (maybe?)
2223

2324
For more details on modules, see the example scripts, or look for `README.md` files in the `modules/<module>` directory.
2425

25-
# Building/using
26+
## Building/using
2627

2728
1. `go get -u github.com/kraken-hpc/uinit/cmds/uinit`
2829
This will build `uinit` and place it in `$GOPATH/bin`.
2930
2. Write a script (see example `*.script` files)
3031
3. Run it, and either name the script `./uinit.script`, or pass it as a commandline argument.
3132

32-
# Building into u-root
33+
## Using as a package
34+
35+
As of v0.2.0, `uinit` can also be used as a Go package. This package will let your application run `uinit` scripts natively.
36+
37+
As an example, to load and run a script from a file:
38+
39+
```go
40+
s, err := uinit.NewScriptFromFile("myscript.script", logger)
41+
if err != nil {
42+
log.Fatalf("failed to load script: %v", err)
43+
}
44+
if err = s.Run(); err != nil {
45+
log.Fatalf("failed to run script: %v", err)
46+
}
47+
```
48+
49+
For more details, see the package documentation at [https://pkg.go.dev/github.com/kraken-hpc/uinit](https://pkg.go.dev/github.com/kraken-hpc/uinit).
50+
51+
52+
## Building into u-root
3353

3454
You can build uinit directly into [u-root](https://github.com/u-root/u-root) by adding the following commandline options to your u-root build:
3555
`-uinitcmd /bbin/uinit github.com/kraken-hpc/uinit/cmds/uinit`
@@ -39,4 +59,4 @@ If you intend to boot something with `systemd`out of this, you'll want to:
3959
1. have `uroot.systemd` on your kernel commandline
4060
2. put a built `uinit` named `inito` in the root of your `base cpio`
4161

42-
# Enjoy
62+
## Enjoy

cmds/uinit/module_load.go

Lines changed: 0 additions & 18 deletions
This file was deleted.

cmds/uinit/subscript.script

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
- name: Hello from subscript.script
3+
module: echo
4+
args:
5+
text: "I'm the subscript"

cmds/uinit/uinit.go

Lines changed: 7 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
package main
22

33
import (
4-
"bytes"
54
"fmt"
65
"io"
7-
"io/ioutil"
86
"log"
97
"os"
10-
"text/template"
118

12-
"github.com/jinzhu/copier"
139
"github.com/kraken-hpc/uinit"
14-
15-
"gopkg.in/yaml.v3"
10+
"github.com/kraken-hpc/uinit/modules"
1611
)
1712

1813
var config = struct {
@@ -27,57 +22,6 @@ Usage: uinit [<script>]
2722
`, config.scriptFile)
2823
}
2924

30-
// a task is an individual item in the yaml script
31-
type task struct {
32-
Name string
33-
Module string
34-
Args yaml.Node
35-
Loop []string
36-
}
37-
38-
// templateNode this is recursive
39-
func templateNode(ctx *uinit.ModuleContext, a *yaml.Node) (err error) {
40-
// too hacky depend on this string never changing?
41-
if a.ShortTag() == "!!str" {
42-
c := a.Content
43-
t := template.Must(template.New("vars").Parse(a.Value)) // we could probably find a clever way to reuse this
44-
w := bytes.NewBuffer([]byte{})
45-
if err = t.Execute(w, ctx.Vars.GetMap()); err != nil {
46-
return fmt.Errorf("failed to template value: %s: %v", a.Value, err)
47-
}
48-
if err = a.Encode(w.String()); err != nil {
49-
return fmt.Errorf("failed to (re)encode value: %v", err)
50-
}
51-
a.Content = c
52-
}
53-
for _, n := range a.Content {
54-
templateNode(ctx, n)
55-
}
56-
return
57-
}
58-
59-
func run(ctx *uinit.ModuleContext, m string, a *yaml.Node) (err error) {
60-
var mod uinit.Module
61-
var ok bool
62-
if mod, ok = modules[m]; !ok {
63-
return fmt.Errorf("no module by the name of: %s", m)
64-
}
65-
66-
if err = templateNode(ctx, a); err != nil {
67-
return fmt.Errorf("failed templating arguments: %v", err)
68-
}
69-
70-
args := mod.Args()
71-
if err = a.Decode(args); err != nil {
72-
return fmt.Errorf("failed to parse arguments: %v", err)
73-
}
74-
pre := ctx.Log.Prefix()
75-
ctx.Log.SetPrefix(pre + m + ": ")
76-
err = mod.Run(ctx, args)
77-
ctx.Log.SetPrefix(pre)
78-
return
79-
}
80-
8125
func main() {
8226
if len(os.Args) > 2 {
8327
usage()
@@ -86,54 +30,23 @@ func main() {
8630
if len(os.Args) == 2 {
8731
config.scriptFile = os.Args[1]
8832
}
33+
modules.InitAll()
8934

9035
log.SetPrefix("uinit: ")
9136
log.SetFlags(log.Lmsgprefix | log.Ltime | log.Ldate)
9237
log.Printf("using script at: %s", config.scriptFile)
93-
sout, err := ioutil.ReadFile(config.scriptFile)
38+
script, err := uinit.NewScriptFromFile(config.scriptFile, nil)
9439
if err != nil {
95-
log.Fatalf("failed to read script file: %v", err)
96-
}
97-
98-
script := []task{}
99-
if err = yaml.Unmarshal(sout, &script); err != nil {
100-
log.Fatalf("failed to parse script: %v", err)
40+
log.Fatalf("failed to read script: %v", err)
10141
}
10242

10343
log.Printf("using log file: %s", config.logFile)
10444
logFile, err := os.OpenFile(config.logFile, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
10545
if err != nil {
10646
log.Fatalf("failed to open log file: %v", err)
10747
}
108-
109-
ctx := &uinit.ModuleContext{
110-
Vars: uinit.NewSimpleKV(),
111-
Log: log.New(io.MultiWriter(os.Stdout, logFile), "uinit: ", log.Lmsgprefix|log.Ltime|log.Ldate),
112-
}
113-
114-
succeed := 0
115-
total := len(script)
116-
ctx.Log.Printf("starting uinit script with %d tasks...", total)
117-
for i, t := range script {
118-
if t.Loop == nil {
119-
t.Loop = []string{""}
120-
}
121-
ctx.Log.Printf("(%d/%d) task: %s: %s", i+1, total, t.Module, t.Name)
122-
for _, item := range t.Loop {
123-
if item != "" {
124-
ctx.Log.Printf("(item: %s)", item)
125-
}
126-
ctx.Vars.Set("item", item)
127-
// we have to copy, otherwise we overwrite our template
128-
args := &yaml.Node{}
129-
copier.CopyWithOption(args, &t.Args, copier.Option{DeepCopy: true})
130-
if err = run(ctx, t.Module, args); err != nil {
131-
ctx.Log.Printf("(%d/%d) task failed: %v", i+1, total, err)
132-
} else {
133-
ctx.Log.Printf("(%d/%d) task succeed.", i+1, total)
134-
succeed++
135-
}
136-
}
48+
script.Context.Log = log.New(io.MultiWriter(os.Stdout, logFile), "uinit: ", log.Lmsgprefix|log.Ltime|log.Ldate)
49+
if err = script.Run(); err != nil {
50+
log.Fatalf("script failed to run: %v", err)
13751
}
138-
ctx.Log.Printf("(%d/%d) tasks succeeded. Script finished. Exiting.", succeed, len(script))
13952
}

cmds/uinit/uinit.script

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,28 @@
4343
- "a"
4444
- "b"
4545
- "c"
46-
- name: Run ls via shell
46+
- name: Run sub-script with one task
47+
module: script
48+
args:
49+
tasks:
50+
- name: Echo something in a the subscript
51+
module: echo
52+
args:
53+
text: "something"
54+
- name: Run sub-script from file
55+
module: script
56+
args:
57+
file: subscript.script
58+
- name: Run a sub-script from file plus an extra task
59+
module: script
60+
args:
61+
file: subscript.script
62+
tasks:
63+
- name: This is the extra task
64+
module: echo
65+
args:
66+
text: "extra task..."
67+
- name: Run ls via shell (exec)
4768
module: command
4869
args:
4970
cmd: ls -l

go.mod

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ module github.com/kraken-hpc/uinit
33
go 1.15
44

55
require (
6-
github.com/bensallen/rbd v0.0.0-20201123204607-9b994a7784d0
6+
github.com/bensallen/rbd v0.0.0-20210224155049-baf486eceefa
7+
github.com/davecgh/go-spew v1.1.1 // indirect
78
github.com/dustin/go-humanize v1.0.0 // indirect
8-
github.com/jinzhu/copier v0.2.8
9-
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
9+
github.com/jinzhu/copier v0.3.2
10+
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
1011
)

go.sum

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
22
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
3-
github.com/bensallen/rbd v0.0.0-20201123204607-9b994a7784d0 h1:hdzFuDcnAr8n5TXGVZkGxGKOJ5pfivv0rKICVmG/WzY=
4-
github.com/bensallen/rbd v0.0.0-20201123204607-9b994a7784d0/go.mod h1:scQzzcMu4X4w0L6rELxUERr68HS2Lqu/NYdnxw72sV8=
3+
github.com/bensallen/rbd v0.0.0-20210224155049-baf486eceefa h1:fk3cRl+COO4Ps5eiMTFD2VIve8PN3yfLztDDsuKUZjI=
4+
github.com/bensallen/rbd v0.0.0-20210224155049-baf486eceefa/go.mod h1:2CDopFVfYqEf77T3xHJDcvuCULhkdQ4HgtstEVoPtfM=
55
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
66
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
77
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
8-
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
98
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
9+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
10+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1011
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
1112
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
1213
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@@ -26,8 +27,8 @@ github.com/google/goexpect v0.0.0-20200816234442-b5b77125c2c5 h1:WgPsDN4gp2CYXtw
2627
github.com/google/goexpect v0.0.0-20200816234442-b5b77125c2c5/go.mod h1:n1ej5+FqyEytMt/mugVDZLIiqTMO+vsrgY+kM6ohzN0=
2728
github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f h1:5CjVwnuUcp5adK4gmY6i72gpVFVnZDP2h5TmPScB6u4=
2829
github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f/go.mod h1:nOFQdrUlIlx6M6ODdSpBj1NVA+VgLC6kmw60mkw34H4=
29-
github.com/jinzhu/copier v0.2.8 h1:N8MbL5niMwE3P4dOwurJixz5rMkKfujmMRFmAanSzWE=
30-
github.com/jinzhu/copier v0.2.8/go.mod h1:24xnZezI2Yqac9J61UC6/dG/k76ttpq0DdJI3QmUvro=
30+
github.com/jinzhu/copier v0.3.2 h1:QdBOCbaouLDYaIPFfi1bKv5F5tPpeTwXe4sD0jqtz5w=
31+
github.com/jinzhu/copier v0.3.2/go.mod h1:24xnZezI2Yqac9J61UC6/dG/k76ttpq0DdJI3QmUvro=
3132
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
3233
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
3334
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -69,8 +70,9 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h
6970
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
7071
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
7172
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
72-
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
73-
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
73+
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
74+
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
75+
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
7476
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
7577
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
7678
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -80,8 +82,8 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
8082
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
8183
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
8284
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
83-
golang.org/x/tools v0.0.0-20201119174615-0557df368a99 h1:n5vf2xiiTUJDdUAV0Jz8zchHkBWp2NURAlIjghNNx+c=
84-
golang.org/x/tools v0.0.0-20201119174615-0557df368a99/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
85+
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
86+
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
8587
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
8688
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
8789
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -100,7 +102,7 @@ google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
100102
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
101103
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
102104
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
103-
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
104-
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
105+
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
106+
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
105107
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
106108
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

interfaces.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@ type KeyValue interface {
1313
}
1414

1515
// ModuleContext gets passed to modules when they Run
16+
// Vars provides a KeyValue store to be used by the script
17+
// Log provides output logging capabilities for the script
1618
type ModuleContext struct {
1719
Vars KeyValue
1820
Log *log.Logger
1921
}
2022

2123
// A Module is a named hook that can perform some task in our script
24+
// A Script consists of a set of Tasks that use Modules to do work
2225
type Module interface {
2326
Args() interface{}
2427
Run(ctx *ModuleContext, args interface{}) error

modules/modules_darwin.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package modules
2+
3+
import (
4+
"github.com/kraken-hpc/uinit"
5+
"github.com/kraken-hpc/uinit/modules/cmdline"
6+
"github.com/kraken-hpc/uinit/modules/command"
7+
"github.com/kraken-hpc/uinit/modules/echo"
8+
"github.com/kraken-hpc/uinit/modules/script"
9+
"github.com/kraken-hpc/uinit/modules/setvar"
10+
)
11+
12+
func InitAll() {
13+
uinit.Modules = map[string]uinit.Module{
14+
"echo": &echo.Echo{},
15+
"setvar": &setvar.SetVar{},
16+
"command": &command.Command{},
17+
"cmdline": &cmdline.CmdLine{},
18+
"script": &script.Script{},
19+
}
20+
}

0 commit comments

Comments
 (0)