diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..8ebac61 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "cSpell.words": [ + "MINIT" + ] +} \ No newline at end of file diff --git a/pkg/munit/load.go b/pkg/munit/load.go deleted file mode 100644 index f5393d5..0000000 --- a/pkg/munit/load.go +++ /dev/null @@ -1,308 +0,0 @@ -package munit - -import ( - "errors" - "fmt" - "io" - "os" - "path/filepath" - "strconv" - "strings" - - "github.com/yankeguo/minit/pkg/shellquote" - "gopkg.in/yaml.v3" -) - -func LoadArgs(args []string) (unit Unit, ok bool, err error) { - var opts []string - - // fix a history issue - for len(args) > 0 { - if filepath.Base(args[0]) == "minit" { - args = args[1:] - } else { - break - } - } - - // extract arguments after '--' if existed - for i, item := range args { - if item == "--" { - opts = args[0:i] - args = args[i+1:] - break - } - } - - if len(args) == 0 { - return - } - - unit = Unit{ - Name: "arg-main", - Kind: KindDaemon, - Command: args, - } - - // opts decoding - for _, opt := range opts { - if strings.HasSuffix(opt, "-"+KindOnce) { - unit.Kind = KindOnce - } - } - - ok = true - - return -} - -const ( - UnitPrefix = "MINIT_UNIT_" -) - -// DetectEnvInfixes detects infixes from environment variables -func DetectEnvInfixes() (infixes []string) { - _infixes := map[string]struct{}{} - - for _, item := range os.Environ() { - splits := strings.SplitN(item, "=", 2) - if len(splits) != 2 { - continue - } - - key := splits[0] - if !strings.HasPrefix(key, UnitPrefix) { - continue - } - key = strings.TrimPrefix(key, UnitPrefix) - if strings.HasSuffix(key, "_COMMAND") { - key = strings.TrimSuffix(key, "_COMMAND") - if key == "" { - continue - } - _infixes[key] = struct{}{} - } else if strings.HasSuffix(key, "_FILES") { - key = strings.TrimSuffix(key, "_FILES") - if key == "" { - continue - } - if os.Getenv(UnitPrefix+key+"_KIND") == KindRender { - _infixes[key] = struct{}{} - } - } - } - - for infix := range _infixes { - infixes = append(infixes, infix) - } - - return -} - -// LoadFromEnvWithInfix loads unit from environment variables with infix -// e.g. MINIT_MAIN_KIND, MINIT_MAIN_NAME, MINIT_MAIN_COMMAND -func LoadFromEnvWithInfix(infix string) (unit Unit, ok bool, err error) { - // kind - unit.Kind = os.Getenv(UnitPrefix + infix + "_KIND") - - if unit.Kind == "" { - unit.Kind = KindDaemon - } - - switch unit.Kind { - case KindDaemon, KindOnce, KindCron, KindRender: - default: - err = errors.New("unsupported $" + UnitPrefix + infix + "_KIND: " + unit.Kind) - return - } - - // name, group, count - unit.Name = os.Getenv(UnitPrefix + infix + "_NAME") - if unit.Name == "" { - unit.Name = "env-" + strings.ToLower(infix) - } - unit.Group = os.Getenv(UnitPrefix + infix + "_GROUP") - unit.Count, _ = strconv.Atoi(os.Getenv("MINIT_" + infix + "_COUNT")) - - // command, dir, shell, charset - switch unit.Kind { - case KindDaemon, KindOnce, KindCron: - cmd := os.Getenv(UnitPrefix + infix + "_COMMAND") - - if unit.Command, err = shellquote.Split(cmd); err != nil { - return - } - - if len(unit.Command) == 0 { - err = errors.New("missing environment variable $MINIT_" + infix + "_COMMAND") - return - } - - unit.Dir = os.Getenv(UnitPrefix + infix + "_DIR") - unit.Shell = os.Getenv(UnitPrefix + infix + "_SHELL") - unit.Charset = os.Getenv(UnitPrefix + infix + "_CHARSET") - - for _, item := range strings.Split(os.Getenv(UnitPrefix+infix+"_ENV"), ";") { - item = strings.TrimSpace(item) - splits := strings.SplitN(item, "=", 2) - if len(splits) == 2 { - if unit.Env == nil { - unit.Env = make(map[string]string) - } - unit.Env[splits[0]] = splits[1] - } - } - } - - // cron, immediate - if unit.Kind == KindCron { - unit.Cron = os.Getenv(UnitPrefix + infix + "_CRON") - - if unit.Cron == "" { - err = errors.New("missing environment variable $" + UnitPrefix + infix + "_CRON while $" + UnitPrefix + infix + "_KIND is 'cron'") - return - } - - unit.Immediate, _ = strconv.ParseBool(os.Getenv(UnitPrefix + infix + "_IMMEDIATE")) - } - - // raw, files - if unit.Kind == KindRender { - unit.Raw, _ = strconv.ParseBool(os.Getenv(UnitPrefix + infix + "_RAW")) - - for _, item := range strings.Split(os.Getenv(UnitPrefix+infix+"_FILES"), ";") { - item = strings.TrimSpace(item) - if item != "" { - unit.Files = append(unit.Files, item) - } - } - - if len(unit.Files) == 0 { - err = errors.New("missing environment variable $" + UnitPrefix + infix + "_FILES while $" + UnitPrefix + infix + "_KIND is 'render'") - return - } - } - - // blocking - if unit.Kind == KindOnce { - if nb, err := strconv.ParseBool(strings.TrimSpace(os.Getenv(UnitPrefix + infix + "_BLOCKING"))); err == nil && !nb { - unit.Blocking = new(bool) - *unit.Blocking = false - } - } - - ok = true - - return -} - -func LoadEnv() (unit Unit, ok bool, err error) { - cmd := strings.TrimSpace(os.Getenv("MINIT_MAIN")) - if cmd == "" { - return - } - - name := strings.TrimSpace(os.Getenv("MINIT_MAIN_NAME")) - if name == "" { - name = "env-main" - } - - var ( - cron string - immediate bool - ) - - kind := strings.TrimSpace(os.Getenv("MINIT_MAIN_KIND")) - - switch kind { - case KindDaemon, KindOnce: - case KindCron: - cron = strings.TrimSpace(os.Getenv("MINIT_MAIN_CRON")) - - if cron == "" { - err = errors.New("missing environment variable $MINIT_MAIN_CRON while $MINIT_MAIN_KIND is 'cron'") - return - } - - immediate, _ = strconv.ParseBool(os.Getenv("MINIT_MAIN_IMMEDIATE")) - case "": - if once, _ := strconv.ParseBool(strings.TrimSpace(os.Getenv("MINIT_MAIN_ONCE"))); once { - kind = KindOnce - } else { - kind = KindDaemon - } - default: - err = errors.New("unsupported $MINIT_MAIN_KIND: " + kind) - return - } - - var cmds []string - if cmds, err = shellquote.Split(cmd); err != nil { - return - } - - unit = Unit{ - Name: name, - Group: strings.TrimSpace(os.Getenv("MINIT_MAIN_GROUP")), - Kind: kind, - Cron: cron, - Immediate: immediate, - Command: cmds, - Dir: strings.TrimSpace(os.Getenv("MINIT_MAIN_DIR")), - Charset: strings.TrimSpace(os.Getenv("MINIT_MAIN_CHARSET")), - } - - if unit.Kind == KindOnce { - if nb, err := strconv.ParseBool(strings.TrimSpace(os.Getenv("MINIT_MAIN_BLOCKING"))); err == nil && !nb { - unit.Blocking = new(bool) - *unit.Blocking = false - } - } - - ok = true - return -} - -func LoadFile(filename string) (units []Unit, err error) { - var f *os.File - if f, err = os.Open(filename); err != nil { - return - } - defer f.Close() - - dec := yaml.NewDecoder(f) - for { - var unit Unit - if err = dec.Decode(&unit); err != nil { - if err == io.EOF { - err = nil - } else { - err = fmt.Errorf("failed to decode unit file %s: %s", filename, err.Error()) - } - return - } - - if unit.Kind == "" { - continue - } - - units = append(units, unit) - } -} - -func LoadDir(dir string) (units []Unit, err error) { - for _, ext := range []string{"*.yml", "*.yaml"} { - var files []string - if files, err = filepath.Glob(filepath.Join(dir, ext)); err != nil { - return - } - for _, file := range files { - var _units []Unit - if _units, err = LoadFile(file); err != nil { - return - } - units = append(units, _units...) - } - } - return -} diff --git a/pkg/munit/load_args.go b/pkg/munit/load_args.go new file mode 100644 index 0000000..3269b20 --- /dev/null +++ b/pkg/munit/load_args.go @@ -0,0 +1,50 @@ +package munit + +import ( + "path/filepath" + "strings" +) + +// LoadArgs loads unit from command line arguments +func LoadArgs(args []string) (unit Unit, ok bool, err error) { + var opts []string + + // fix a history issue + for len(args) > 0 { + if filepath.Base(args[0]) == "minit" { + args = args[1:] + } else { + break + } + } + + // extract arguments after '--' if existed + for i, item := range args { + if item == "--" { + opts = args[0:i] + args = args[i+1:] + break + } + } + + if len(args) == 0 { + return + } + + unit = Unit{ + Name: "arg-main", + Kind: KindDaemon, + Command: args, + } + + // opts decoding + for _, opt := range opts { + if strings.HasSuffix(opt, "-"+KindOnce) { + unit.Kind = KindOnce + } + } + + ok = true + + return +} diff --git a/pkg/munit/load_test.go b/pkg/munit/load_args_test.go similarity index 71% rename from pkg/munit/load_test.go rename to pkg/munit/load_args_test.go index bdddd2c..5fba358 100644 --- a/pkg/munit/load_test.go +++ b/pkg/munit/load_args_test.go @@ -1,9 +1,9 @@ package munit import ( - "github.com/stretchr/testify/require" - "os" "testing" + + "github.com/stretchr/testify/require" ) func TestLoadArgs(t *testing.T) { @@ -79,27 +79,3 @@ func TestLoadArgs(t *testing.T) { require.Equal(t, []string{"sleep", "30"}, unit.Command) require.Equal(t, KindOnce, unit.Kind) } - -func TestLoadEnv(t *testing.T) { - os.Setenv("MINIT_MAIN", "hello 'world destroyer'") - os.Setenv("MINIT_MAIN_KIND", "cron") - os.Setenv("MINIT_MAIN_NAME", "test-main") - os.Setenv("MINIT_MAIN_CRON", "1 2 3 4 5") - os.Setenv("MINIT_MAIN_GROUP", "bbb") - os.Setenv("MINIT_MAIN_CHARSET", "gbk") - - unit, ok, err := LoadEnv() - require.NoError(t, err) - require.True(t, ok) - require.Equal(t, Unit{ - Kind: "cron", - Name: "test-main", - Cron: "1 2 3 4 5", - Group: "bbb", - Command: []string{ - "hello", - "world destroyer", - }, - Charset: "gbk", - }, unit) -} diff --git a/pkg/munit/load_env.go b/pkg/munit/load_env.go new file mode 100644 index 0000000..438cb79 --- /dev/null +++ b/pkg/munit/load_env.go @@ -0,0 +1,239 @@ +package munit + +import ( + "errors" + "os" + "strconv" + "strings" + + "github.com/yankeguo/minit/pkg/shellquote" +) + +var ( + osEnviron = os.Environ + osGetenv = os.Getenv +) + +const ( + EnvPrefixUnit = "MINIT_UNIT_" +) + +// DetectEnvInfixes detects infixes from environment variables +func DetectEnvInfixes() (infixes []string) { + _infixes := map[string]struct{}{} + + for _, item := range osEnviron() { + splits := strings.SplitN(item, "=", 2) + if len(splits) != 2 { + continue + } + + key := splits[0] + if !strings.HasPrefix(key, EnvPrefixUnit) { + continue + } + key = strings.TrimPrefix(key, EnvPrefixUnit) + if strings.HasSuffix(key, "_COMMAND") { + // anything with _COMMAND is a unit + key = strings.TrimSuffix(key, "_COMMAND") + if key == "" { + continue + } + _infixes[key] = struct{}{} + } else if strings.HasSuffix(key, "_FILES") { + // anything with _FILES and has _KIND set to render is a render unit + key = strings.TrimSuffix(key, "_FILES") + if key == "" { + continue + } + if osGetenv(EnvPrefixUnit+key+"_KIND") == KindRender { + _infixes[key] = struct{}{} + } + } + } + + for infix := range _infixes { + infixes = append(infixes, infix) + } + + return +} + +// LoadEnvWithInfix loads unit from environment variables with infix +// e.g. MINIT_UNIT_HELLO_KIND, MINIT_UNIT_HELLO_NAME, MINIT_UNIT_HELLO_COMMAND +func LoadEnvWithInfix(infix string) (unit Unit, ok bool, err error) { + // kind + unit.Kind = osGetenv(EnvPrefixUnit + infix + "_KIND") + + if unit.Kind == "" { + unit.Kind = KindDaemon + } + + switch unit.Kind { + case KindDaemon, KindOnce, KindCron, KindRender: + default: + err = errors.New("unsupported $" + EnvPrefixUnit + infix + "_KIND: " + unit.Kind) + return + } + + // name, group, count + unit.Name = osGetenv(EnvPrefixUnit + infix + "_NAME") + if unit.Name == "" { + unit.Name = "env-" + strings.ToLower(infix) + } + unit.Group = osGetenv(EnvPrefixUnit + infix + "_GROUP") + unit.Count, _ = strconv.Atoi(osGetenv(EnvPrefixUnit + infix + "_COUNT")) + + // command, dir, shell, charset + switch unit.Kind { + case KindDaemon, KindOnce, KindCron: + cmd := osGetenv(EnvPrefixUnit + infix + "_COMMAND") + + if unit.Command, err = shellquote.Split(cmd); err != nil { + return + } + + if len(unit.Command) == 0 { + err = errors.New("missing environment variable $MINIT_" + infix + "_COMMAND") + return + } + + unit.Dir = osGetenv(EnvPrefixUnit + infix + "_DIR") + unit.Shell = osGetenv(EnvPrefixUnit + infix + "_SHELL") + unit.Charset = osGetenv(EnvPrefixUnit + infix + "_CHARSET") + + for _, item := range strings.Split(osGetenv(EnvPrefixUnit+infix+"_ENV"), ";") { + item = strings.TrimSpace(item) + splits := strings.SplitN(item, "=", 2) + if len(splits) == 2 { + if unit.Env == nil { + unit.Env = make(map[string]string) + } + unit.Env[splits[0]] = splits[1] + } + } + } + + // cron, immediate + if unit.Kind == KindCron { + unit.Cron = osGetenv(EnvPrefixUnit + infix + "_CRON") + + if unit.Cron == "" { + err = errors.New("missing environment variable $" + EnvPrefixUnit + infix + "_CRON while $" + EnvPrefixUnit + infix + "_KIND is 'cron'") + return + } + + unit.Immediate, _ = strconv.ParseBool(osGetenv(EnvPrefixUnit + infix + "_IMMEDIATE")) + } + + // raw, files + if unit.Kind == KindRender { + unit.Raw, _ = strconv.ParseBool(osGetenv(EnvPrefixUnit + infix + "_RAW")) + + for _, item := range strings.Split(osGetenv(EnvPrefixUnit+infix+"_FILES"), ";") { + item = strings.TrimSpace(item) + if item != "" { + unit.Files = append(unit.Files, item) + } + } + + if len(unit.Files) == 0 { + err = errors.New("missing environment variable $" + EnvPrefixUnit + infix + "_FILES while $" + EnvPrefixUnit + infix + "_KIND is 'render'") + return + } + } + + // blocking + if unit.Kind == KindOnce { + if nb, err := strconv.ParseBool(strings.TrimSpace(osGetenv(EnvPrefixUnit + infix + "_BLOCKING"))); err == nil && !nb { + unit.Blocking = new(bool) + *unit.Blocking = false + } + } + + // critical + unit.Critical, _ = strconv.ParseBool(osGetenv(EnvPrefixUnit + infix + "_CRITICAL")) + + // success codes + for _, item := range strings.Split(osGetenv(EnvPrefixUnit+infix+"_SUCCESS_CODES"), ",") { + item = strings.TrimSpace(item) + if item == "" { + continue + } + if code, err := strconv.Atoi(item); err == nil { + unit.SuccessCodes = append(unit.SuccessCodes, code) + } + } + + ok = true + + return +} + +// LoadEnv loads legacy main unit from environment variables +func LoadEnv() (unit Unit, ok bool, err error) { + cmd := strings.TrimSpace(osGetenv("MINIT_MAIN")) + if cmd == "" { + return + } + + name := strings.TrimSpace(osGetenv("MINIT_MAIN_NAME")) + if name == "" { + name = "env-main" + } + + var ( + cron string + immediate bool + ) + + kind := strings.TrimSpace(osGetenv("MINIT_MAIN_KIND")) + + switch kind { + case KindDaemon, KindOnce: + case KindCron: + cron = strings.TrimSpace(osGetenv("MINIT_MAIN_CRON")) + + if cron == "" { + err = errors.New("missing environment variable $MINIT_MAIN_CRON while $MINIT_MAIN_KIND is 'cron'") + return + } + + immediate, _ = strconv.ParseBool(osGetenv("MINIT_MAIN_IMMEDIATE")) + case "": + if once, _ := strconv.ParseBool(strings.TrimSpace(osGetenv("MINIT_MAIN_ONCE"))); once { + kind = KindOnce + } else { + kind = KindDaemon + } + default: + err = errors.New("unsupported $MINIT_MAIN_KIND: " + kind) + return + } + + var cmds []string + if cmds, err = shellquote.Split(cmd); err != nil { + return + } + + unit = Unit{ + Name: name, + Group: strings.TrimSpace(osGetenv("MINIT_MAIN_GROUP")), + Kind: kind, + Cron: cron, + Immediate: immediate, + Command: cmds, + Dir: strings.TrimSpace(osGetenv("MINIT_MAIN_DIR")), + Charset: strings.TrimSpace(osGetenv("MINIT_MAIN_CHARSET")), + } + + if unit.Kind == KindOnce { + if nb, err := strconv.ParseBool(strings.TrimSpace(osGetenv("MINIT_MAIN_BLOCKING"))); err == nil && !nb { + unit.Blocking = new(bool) + *unit.Blocking = false + } + } + + ok = true + return +} diff --git a/pkg/munit/load_env_test.go b/pkg/munit/load_env_test.go new file mode 100644 index 0000000..2764178 --- /dev/null +++ b/pkg/munit/load_env_test.go @@ -0,0 +1,161 @@ +package munit + +import ( + "os" + "sort" + "testing" + + "github.com/stretchr/testify/require" +) + +func replaceTestEnv(m map[string]string) { + osGetenv = func(key string) string { + return m[key] + } + osEnviron = func() []string { + var env []string + for k, v := range m { + env = append(env, k+"="+v) + } + return env + } +} + +func restoreTestEnv() { + osGetenv = os.Getenv + osEnviron = os.Environ +} + +func TestDetectEnvInfixes(t *testing.T) { + replaceTestEnv(map[string]string{ + "MINIT_UNIT_MAIN_COMMAND": "hello", + "MINIT_UNIT_COMMAND": "hello", + "MINIT_UNIT_A_FILES": "hello", + "MINIT_UNIT_B_FILES": "hello", + "MINIT_UNIT_B_KIND": "render", + }) + defer restoreTestEnv() + + infixes := DetectEnvInfixes() + sort.StringSlice(infixes).Sort() + + require.Equal(t, []string{"B", "MAIN"}, infixes) +} + +func TestLoadEnvWithInfix(t *testing.T) { + replaceTestEnv(map[string]string{ + "MINIT_UNIT_A1_COMMAND": "echo 'hello world'", + "MINIT_UNIT_A2_COMMAND": "echo 'hello world'", + "MINIT_UNIT_A2_KIND": "cron", + "MINIT_UNIT_A2_CRON": "* * * * *", + "MINIT_UNIT_A2_NAME": "a2", + "MINIT_UNIT_A2_IMMEDIATE": "true", + "MINIT_UNIT_A2_GROUP": "abc", + "MINIT_UNIT_A2_COUNT": "3", + "MINIT_UNIT_A2_DIR": "/opt", + "MINIT_UNIT_A2_SHELL": "/bin/zsh", + "MINIT_UNIT_A2_CHARSET": "gbk", + "MINIT_UNIT_A2_ENV": "a=b;c=d", + "MINIT_UNIT_A2_CRITICAL": "true", + "MINIT_UNIT_A2_SUCCESS_CODES": "114,514", + "MINIT_UNIT_A3_COMMAND": "echo 'hello world'", + "MINIT_UNIT_A3_KIND": "once", + "MINIT_UNIT_A3_BLOCKING": "false", + "MINIT_UNIT_A4_KIND": "render", + "MINIT_UNIT_A4_FILES": "hello.txt;world.txt", + "MINIT_UNIT_A4_RAW": "true", + }) + defer restoreTestEnv() + + unit, ok, err := LoadEnvWithInfix("A1") + require.NoError(t, err) + require.True(t, ok) + require.Equal(t, Unit{ + Kind: KindDaemon, + Name: "env-a1", + Command: []string{ + "echo", + "hello world", + }, + }, unit) + + unit, ok, err = LoadEnvWithInfix("A2") + require.NoError(t, err) + require.True(t, ok) + require.Equal(t, Unit{ + Kind: KindCron, + Name: "a2", + Command: []string{ + "echo", + "hello world", + }, + Immediate: true, + Cron: "* * * * *", + Group: "abc", + Count: 3, + Dir: "/opt", + Shell: "/bin/zsh", + Charset: "gbk", + Env: map[string]string{ + "a": "b", + "c": "d", + }, + Critical: true, + SuccessCodes: []int{114, 514}, + }, unit) + + blockingTrue := false + + unit, ok, err = LoadEnvWithInfix("A3") + require.NoError(t, err) + require.True(t, ok) + require.Equal(t, Unit{ + Kind: KindOnce, + Name: "env-a3", + Blocking: &blockingTrue, + Command: []string{ + "echo", + "hello world", + }, + }, unit) + + unit, ok, err = LoadEnvWithInfix("A4") + require.NoError(t, err) + require.True(t, ok) + require.Equal(t, Unit{ + Kind: KindRender, + Name: "env-a4", + Raw: true, + Files: []string{ + "hello.txt", + "world.txt", + }, + }, unit) +} + +func TestLoadEnv(t *testing.T) { + replaceTestEnv(map[string]string{ + "MINIT_MAIN": "hello 'world destroyer'", + "MINIT_MAIN_KIND": "cron", + "MINIT_MAIN_NAME": "test-main", + "MINIT_MAIN_CRON": "1 2 3 4 5", + "MINIT_MAIN_GROUP": "bbb", + "MINIT_MAIN_CHARSET": "gbk", + }) + defer restoreTestEnv() + + unit, ok, err := LoadEnv() + require.NoError(t, err) + require.True(t, ok) + require.Equal(t, Unit{ + Kind: "cron", + Name: "test-main", + Cron: "1 2 3 4 5", + Group: "bbb", + Command: []string{ + "hello", + "world destroyer", + }, + Charset: "gbk", + }, unit) +} diff --git a/pkg/munit/load_file.go b/pkg/munit/load_file.go new file mode 100644 index 0000000..4c5a17d --- /dev/null +++ b/pkg/munit/load_file.go @@ -0,0 +1,56 @@ +package munit + +import ( + "fmt" + "io" + "os" + "path/filepath" + + "gopkg.in/yaml.v3" +) + +// LoadFile loads units from a file +func LoadFile(filename string) (units []Unit, err error) { + var f *os.File + if f, err = os.Open(filename); err != nil { + return + } + defer f.Close() + + dec := yaml.NewDecoder(f) + for { + var unit Unit + if err = dec.Decode(&unit); err != nil { + if err == io.EOF { + err = nil + } else { + err = fmt.Errorf("failed to decode unit file %s: %s", filename, err.Error()) + } + return + } + + if unit.Kind == "" { + continue + } + + units = append(units, unit) + } +} + +// LoadDir loads units from a directory +func LoadDir(dir string) (units []Unit, err error) { + for _, ext := range []string{"*.yml", "*.yaml"} { + var files []string + if files, err = filepath.Glob(filepath.Join(dir, ext)); err != nil { + return + } + for _, file := range files { + var _units []Unit + if _units, err = LoadFile(file); err != nil { + return + } + units = append(units, _units...) + } + } + return +} diff --git a/pkg/munit/load_file_test.go b/pkg/munit/load_file_test.go new file mode 100644 index 0000000..4ffb859 --- /dev/null +++ b/pkg/munit/load_file_test.go @@ -0,0 +1,57 @@ +package munit + +import ( + "sort" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestLoadDir(t *testing.T) { + units, err := LoadDir("testdata") + require.NoError(t, err) + require.NotEmpty(t, units) + + sort.Slice(units, func(i, j int) bool { + return units[i].Name < units[j].Name + }) + + require.Equal(t, []Unit{ + { + Kind: "once", + Name: "task-1", + Group: "group-echo", + Command: []string{"echo", "once", "$HOME"}, + }, + { + Kind: "daemon", + Name: "task-2", + Group: "group-echo", + Count: 3, + Critical: true, + Shell: "/bin/bash", + Command: []string{"sleep 1 && echo hello world"}, + Charset: "gbk", + SuccessCodes: []int{0, 1, 2}, + }, + { + Kind: "daemon", + Name: "task-3", + Count: 3, + Command: []string{"sleep", "5"}, + }, + { + Kind: "cron", + Name: "task-4", + Command: []string{"echo", "cron"}, + Cron: "@every ${DEBUG_EVERY}", + Immediate: true, + }, + { + Kind: "render", + Name: "task-5", + Raw: true, + Files: []string{"testdata/conf/*.conf"}, + }, + }, units) +} diff --git a/pkg/munit/loader.go b/pkg/munit/loader.go index dacb401..2f8d851 100644 --- a/pkg/munit/loader.go +++ b/pkg/munit/loader.go @@ -78,7 +78,7 @@ func (ld *Loader) Load(opts LoadOptions) (output []Unit, skipped []Unit, err err unit Unit ok bool ) - if unit, ok, err = LoadFromEnvWithInfix(infix); err != nil { + if unit, ok, err = LoadEnvWithInfix(infix); err != nil { return } if ok { diff --git a/pkg/munit/testdata/test1.yml b/pkg/munit/testdata/test1.yml index abb11cf..e2d95ab 100644 --- a/pkg/munit/testdata/test1.yml +++ b/pkg/munit/testdata/test1.yml @@ -1,6 +1,7 @@ name: task-1 kind: once group: group-echo +block: false command: - echo - once @@ -11,6 +12,10 @@ kind: daemon group: group-echo count: 3 shell: /bin/bash +critical: true +charset: gbk command: - sleep 1 && echo hello world ---- \ No newline at end of file +success_codes: [0, 1, 2] +--- + diff --git a/pkg/munit/testdata/test2.yml b/pkg/munit/testdata/test2.yml index 5523534..479d83a 100644 --- a/pkg/munit/testdata/test2.yml +++ b/pkg/munit/testdata/test2.yml @@ -8,11 +8,13 @@ command: name: task-4 kind: cron cron: "@every ${DEBUG_EVERY}" +immediate: true command: - echo - cron --- name: task-5 kind: render +raw: true files: - testdata/conf/*.conf