diff --git a/README.md b/README.md index 865da46..1ffa235 100644 --- a/README.md +++ b/README.md @@ -16,11 +16,11 @@ json2env execute commands with environment variables made from JSON. ## Synopsis ```go -$ echo '{"key":"value"}' | json2env /path/to/command [...] +$ echo '{"key":"value"}' | json2env --keys "key" /path/to/command [...] ``` ```go -$ echo '{"examplekey1":"value1", "examplekey2":"value2"}' | json2env env | grep examplekey +$ echo '{"examplekey1":"value1", "examplekey2":"value2", "examplekey3":"value3"}' | json2env --keys "examplekey1,examplekey2" env | grep examplekey examplekey1=value1 examplekey2=value2 ``` @@ -35,6 +35,8 @@ I wanted to pass secret information as an environment variable to the ECS contai Since this feature is implemented in ECS on EC2, this feature will probably be implemented in Fargate in the future, so I wanted something to convert JSON to environment variables that can be used in the meantime. +And I made it mandatory to specify the name of the environment variable to use so that I can safely remove this tool when I no longer use it. + ## Installation ```console diff --git a/json2env.go b/json2env.go index b5e5cfb..efa81bc 100644 --- a/json2env.go +++ b/json2env.go @@ -8,6 +8,7 @@ import ( "io" "log" "os/exec" + "strings" "github.com/pkg/errors" ) @@ -26,6 +27,7 @@ func Run(ctx context.Context, argv []string, outStream, errStream io.Writer, inS } fs.SetOutput(errStream) ver := fs.Bool("version", false, "display version") + keys := fs.String("keys", "", "conmma separated environment variable names that you want to export") if err := fs.Parse(argv); err != nil { return err @@ -37,6 +39,11 @@ func Run(ctx context.Context, argv []string, outStream, errStream io.Writer, inS if *ver { return printVersion(outStream) } + + if *keys == "" { + return errors.New("keys option is required") + } + var envJSON map[string]string err := json.NewDecoder(inStream).Decode(&envJSON) if err != nil { @@ -47,7 +54,11 @@ func Run(ctx context.Context, argv []string, outStream, errStream io.Writer, inS return errors.Wrap(err, "failed to decode input") } } - newEnv := makeNewEnv(env, envJSON) + + newEnv, err := makeNewEnv(env, envJSON, strings.Split(*keys, ",")) + if err != nil { + return errors.Wrapf(err, "failed to create new env") + } if err := runCommand(command, newEnv, outStream, errStream); err != nil { return errors.Wrapf(err, "failed to run command %+s", command) } @@ -55,14 +66,22 @@ func Run(ctx context.Context, argv []string, outStream, errStream io.Writer, inS return nil } -func makeNewEnv(origEnv []string, json map[string]string) []string { +func makeNewEnv(origEnv []string, json map[string]string, envNames []string) ([]string, error) { newEnv := []string{} - for key, value := range json { + newJSON := make(map[string]string) + for _, name := range envNames { + value, ok := json[name] + if !ok { + return newEnv, errors.New(fmt.Sprintf("%s is not exists in json", name)) + } + newJSON[name] = value + } + for key, value := range newJSON { newEnv = append(newEnv, fmt.Sprintf("%s=%s", key, value)) } // if same key exists origEnv and newEnv, json parameter overwrite the origEnv newEnv = append(origEnv, newEnv...) - return newEnv + return newEnv, nil } func printVersion(out io.Writer) error { diff --git a/json2env_test.go b/json2env_test.go index d10e566..daa95cf 100644 --- a/json2env_test.go +++ b/json2env_test.go @@ -9,8 +9,8 @@ import ( ) func TestNormal(t *testing.T) { - stdin := bytes.NewBufferString("{}") - err := Run(context.Background(), []string{"ls"}, &bytes.Buffer{}, &bytes.Buffer{}, stdin, []string{}) + stdin := bytes.NewBufferString("{\"test\": \"test\"}") + err := Run(context.Background(), []string{"-keys", "test", "ls"}, &bytes.Buffer{}, &bytes.Buffer{}, stdin, []string{}) if err != nil { t.Fatalf("failed test %#v", err) } @@ -18,15 +18,22 @@ func TestNormal(t *testing.T) { func TestErrorIfNotJson(t *testing.T) { stdin := bytes.NewBufferString("{deadbeaf") - err := Run(context.Background(), []string{"ls"}, &bytes.Buffer{}, &bytes.Buffer{}, stdin, []string{}) + err := Run(context.Background(), []string{"-keys", "test", "ls"}, &bytes.Buffer{}, &bytes.Buffer{}, stdin, []string{}) if err == nil { - t.Fatalf("error not occurred, failed test %#v", err) + t.Fatalf("error not occurred, failed test") } } +func TestErrorIfSpecifyNotExistsKeysJson(t *testing.T) { + stdin := bytes.NewBufferString("{\"test\": \"test\"}") + err := Run(context.Background(), []string{"-keys", "notExists", "ls"}, &bytes.Buffer{}, &bytes.Buffer{}, stdin, []string{}) + if err == nil { + t.Fatalf("error not occurred, failed test") + } +} func TestErrorIfCommandNotExists(t *testing.T) { - stdin := bytes.NewBufferString("{deadbeaf") - err := Run(context.Background(), []string{}, &bytes.Buffer{}, &bytes.Buffer{}, stdin, []string{}) + stdin := bytes.NewBufferString("{\"test\": \"test\"}") + err := Run(context.Background(), []string{"-keys", "test"}, &bytes.Buffer{}, &bytes.Buffer{}, stdin, []string{}) if err == nil { t.Fatalf("error not occurred, failed test %#v", err) } @@ -34,7 +41,7 @@ func TestErrorIfCommandNotExists(t *testing.T) { func TestEnv(t *testing.T) { stdin := bytes.NewBufferString("{\"a\": \"after\"}") var outStream bytes.Buffer - err := Run(context.Background(), []string{"env"}, &outStream, &bytes.Buffer{}, stdin, []string{"a=before"}) + err := Run(context.Background(), []string{"-keys", "a", "env"}, &outStream, &bytes.Buffer{}, stdin, []string{"a=before"}) if err != nil { t.Fatalf("failed run %#v", err) } @@ -45,7 +52,10 @@ func TestEnv(t *testing.T) { } func TestGetEnv(t *testing.T) { - env := makeNewEnv([]string{"a=b", "b=b"}, map[string]string{"b": "c", "d": "e"}) + env, err := makeNewEnv([]string{"a=b", "b=b"}, map[string]string{"b": "c", "d": "e"}, []string{"b", "d"}) + if err != nil { + t.Fatalf("failed err:%#v", err) + } sort.Strings(env) expect := []string{"a=b", "b=b", "b=c", "d=e"} sort.Strings(expect) @@ -53,3 +63,23 @@ func TestGetEnv(t *testing.T) { t.Fatalf("failed getEnv test expect: %#v, got: %#v", expect, env) } } + +func TestGetSomeEnv(t *testing.T) { + env, err := makeNewEnv([]string{"a=b", "b=b"}, map[string]string{"b": "c", "d": "e"}, []string{"b"}) + if err != nil { + t.Fatalf("failed err:%#v", err) + } + sort.Strings(env) + expect := []string{"a=b", "b=b", "b=c"} + sort.Strings(expect) + if !reflect.DeepEqual(env, expect) { + t.Fatalf("failed getEnv test expect: %#v, got: %#v", expect, env) + } +} + +func TestNotExistedKey(t *testing.T) { + _, err := makeNewEnv([]string{"a=b", "b=b"}, map[string]string{"b": "c", "d": "e"}, []string{"x"}) + if err == nil { + t.Fatal("failed err") + } +}