diff --git a/env.go b/env.go index 60932ef..941a2fb 100644 --- a/env.go +++ b/env.go @@ -6,8 +6,12 @@ import ( ) func MergeEnv(base, other []string) []string { - baseMap := envSliceToMap(base) otherMap := envSliceToMap(other) + return MergeEnvWithMap(base, otherMap) +} + +func MergeEnvWithMap(base []string, otherMap map[string]string) []string { + baseMap := envSliceToMap(base) for key, value := range otherMap { baseMap[key] = value } diff --git a/flexentry.go b/flexentry.go index e66e620..6345110 100644 --- a/flexentry.go +++ b/flexentry.go @@ -20,8 +20,9 @@ import ( type Entrypoint struct { Executer - mu sync.Mutex - query *gojq.Query + mu sync.Mutex + commandQuery *gojq.Query + environQuery *gojq.Query } func (e *Entrypoint) Run(ctx context.Context, args ...string) error { @@ -103,7 +104,7 @@ func (e *Entrypoint) DetectCommand(ctx context.Context, event Event) ([]string, return commands, nil } if data, ok := event.(map[string]interface{}); ok { - query, err := e.getQuery() + query, err := e.getCommandQuery() if err != nil { return nil, err } @@ -135,20 +136,72 @@ func (e *Entrypoint) DetectCommand(ctx context.Context, event Event) ([]string, return nil, errors.New("FLEXENTRY_COMMAND is required") } -func (e *Entrypoint) getQuery() (*gojq.Query, error) { +func (e *Entrypoint) DetectEnviron(ctx context.Context, event Event) ([]string, error) { + if data, ok := event.(map[string]interface{}); ok { + query, err := e.getEnvironQuery() + if err != nil { + return nil, err + } + environ := make([]string, 0, 1) + iter := query.RunWithContext(ctx, data) + for { + v, ok := iter.Next() + if !ok { + break + } + if err, ok := v.(error); ok { + return nil, fmt.Errorf("environ parse failed: %w", err) + } + if e, ok := v.(string); ok { + environ = MergeEnv(environ, []string{e}) + continue + } + if es, ok := v.([]string); ok { + environ = MergeEnv(environ, es) + continue + } + if es, ok := v.(map[string]string); ok { + environ = MergeEnvWithMap(environ, es) + continue + } + } + return environ, nil + } + return []string{}, nil +} + +func (e *Entrypoint) getCommandQuery() (*gojq.Query, error) { e.mu.Lock() defer e.mu.Unlock() - if e.query != nil { - return e.query, nil + if e.commandQuery != nil { + return e.commandQuery, nil } jqExpr := ".cmd" if j := os.Getenv("FLEXENTRY_COMMAND_JQ_EXPR"); j != "" { jqExpr = j } var err error - e.query, err = gojq.Parse(jqExpr) + e.commandQuery, err = gojq.Parse(jqExpr) + if err != nil { + return nil, err + } + return e.commandQuery, nil +} + +func (e *Entrypoint) getEnvironQuery() (*gojq.Query, error) { + e.mu.Lock() + defer e.mu.Unlock() + if e.environQuery != nil { + return e.environQuery, nil + } + jqExpr := ".env" + if j := os.Getenv("FLEXENTRY_ENVIRON_JQ_EXPR"); j != "" { + jqExpr = j + } + var err error + e.environQuery, err = gojq.Parse(jqExpr) if err != nil { return nil, err } - return e.query, nil + return e.environQuery, nil } diff --git a/flexentry_test.go b/flexentry_test.go index b8a4442..8e0e7f8 100644 --- a/flexentry_test.go +++ b/flexentry_test.go @@ -88,3 +88,79 @@ func TestEntrypointDetectCommand(t *testing.T) { }) } } + +func TestEntrypointDetectEnviron(t *testing.T) { + cases := []struct { + preAction func() + postAction func() + event flexentry.Event + expected []string + }{ + { + event: "echo hoge", + expected: []string{}, + }, + { + event: map[string]interface{}{ + "cmd": "echo hoge", + }, + expected: []string{}, + }, + { + event: map[string]interface{}{ + "cmd": "echo hoge", + "env": map[string]string{ + "HOGE": "fuga", + }, + }, + expected: []string{"HOGE=fuga"}, + }, + { + preAction: func() { + os.Setenv("FLEXENTRY_ENVIRON_JQ_EXPR", ".environ") + }, + postAction: func() { + os.Unsetenv("FLEXENTRY_ENVIRON_JQ_EXPR") + }, + event: map[string]interface{}{ + "cmd": "echo hoge", + "env": map[string]string{ + "HOGE": "fuga", + "FUGA": "hoge", + }, + "environ": map[string]string{ + "HOGE": "hoge", + }, + }, + expected: []string{"HOGE=hoge"}, + }, + { + event: map[string]interface{}{ + "cmd": "echo hoge", + "env": []string{ + "HOGE=fuga", + "FUGA=hoge", + }, + }, + expected: []string{ + "HOGE=fuga", + "FUGA=hoge", + }, + }, + } + + for i, c := range cases { + t.Run(fmt.Sprintf("case.%d", i), func(t *testing.T) { + if c.preAction != nil { + c.preAction() + } + if c.postAction != nil { + defer c.postAction() + } + e := &flexentry.Entrypoint{} + actual, err := e.DetectEnviron(context.Background(), c.event) + require.NoError(t, err) + require.ElementsMatch(t, c.expected, actual) + }) + } +}