github.com/goliatone/go-envset@v0.7.0/cmd/envset/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "log" 6 "math" 7 "os" 8 "time" 9 10 "github.com/goliatone/go-envset/cmd/envset/environment" 11 "github.com/goliatone/go-envset/cmd/envset/metadata" 12 "github.com/goliatone/go-envset/cmd/envset/rc" 13 "github.com/goliatone/go-envset/cmd/envset/template" 14 "github.com/goliatone/go-envset/cmd/envset/version" 15 "github.com/goliatone/go-envset/pkg/config" 16 "github.com/goliatone/go-envset/pkg/exec" 17 18 "github.com/goliatone/go-envset/pkg/envset" 19 20 build "github.com/goliatone/go-envset/pkg/version" 21 22 "github.com/urfave/cli/v2" 23 ) 24 25 var app *cli.App 26 var cnf *config.Config 27 28 func init() { 29 cli.VersionFlag = &cli.BoolFlag{ 30 Name: "version", 31 Aliases: []string{"v"}, 32 Usage: "prints the application version", 33 } 34 35 app = &cli.App{ 36 Name: "envset", 37 Version: build.Tag, 38 Compiled: time.Now(), 39 Authors: []*cli.Author{ 40 { 41 Name: "Goliat One", 42 Email: "envset@goliat.one", 43 }, 44 }, 45 Copyright: "(c) 2015 goliatone", 46 Usage: "Load environment variables to your shell and run a command", 47 HelpName: "envset", 48 UsageText: "envset [environment] -- [command]\n\nEXAMPLE:\n\t envset development -- node index.js\n\t eval $(envset development --isolated=true)\n\t envset development -- say '${MY_GREETING}'", 49 } 50 } 51 52 func main() { 53 args := exec.CliArgs(os.Args) 54 cmd := exec.CmdFromArgs(os.Args) 55 run(args, cmd) 56 } 57 58 func run(args []string, ecmd exec.ExecCmd) { 59 cnf, err := config.Load(".envsetrc") 60 if err != nil { 61 log.Println("Error loading configuration:", err) 62 log.Panic("Ensure you have a valid .envsetrc") 63 } 64 65 subcommands := []*cli.Command{} 66 67 for _, env := range cnf.Environments.Names { 68 subcommands = append(subcommands, environment.GetCommand(env, ecmd, cnf)) 69 } 70 71 app.Commands = append(app.Commands, rc.GetCommand(cnf)) 72 73 app.Commands = append(app.Commands, metadata.GetCommand(cnf)) 74 75 app.Commands = append(app.Commands, template.GetCommand(cnf)) 76 77 app.Commands = append(app.Commands, version.GetCommand(cnf)) 78 79 app.Commands = append(app.Commands, subcommands...) 80 81 app.Flags = []cli.Flag{ 82 &cli.StringFlag{ 83 Name: "env", 84 Usage: "env name matching a section. If not set matches env vars in global scope", 85 Value: envset.DefaultSection, 86 }, 87 &cli.StringFlag{ 88 //This can be an absolute path. If a file name then we recursively look up 89 Name: "env-file", 90 Usage: "`file` with environment definition", 91 Value: cnf.Filename, 92 }, 93 &cli.BoolFlag{ 94 Name: "isolated", 95 Usage: "if false the environment inherits the shell's environment", 96 Value: cnf.Isolated, //call with --isolated=false to show all 97 }, 98 &cli.BoolFlag{ 99 Name: "expand", 100 Usage: "if true we expand environment variables", 101 Value: cnf.Expand, 102 }, 103 &cli.StringSliceFlag{ 104 Name: "required", 105 Aliases: []string{"R"}, 106 Usage: "list of key names that are required to run", 107 }, 108 &cli.StringFlag{ 109 Name: "export-env-name", 110 Aliases: []string{"N"}, 111 Usage: "name of exported variable with current environment name", 112 Value: cnf.ExportEnvName, 113 }, 114 &cli.StringSliceFlag{ 115 Name: "inherit", 116 Aliases: []string{"I"}, 117 Usage: "list of env vars to inherit from shell", 118 }, 119 &cli.BoolFlag{ 120 Name: "restart", 121 Usage: "re-execute command when it exit is error code", 122 Value: cnf.Restart, 123 }, 124 &cli.BoolFlag{ 125 Name: "forever", 126 Usage: "forever re-execute command when it exit is error code", 127 Value: cnf.RestartForever, 128 }, 129 &cli.IntFlag{ 130 Name: "max-restarts", 131 Aliases: []string{"max-restart"}, 132 Usage: "times to restart failed command", 133 Value: cnf.MaxRestarts, 134 }, 135 } 136 137 app.Action = func(c *cli.Context) error { 138 139 //How do we end up here? 140 //If we try to execute a command for an inexistent environment, e.g: 141 // envset ==> show help 142 //we just called: envset 143 if c.NArg() == 0 && c.NumFlags() == 0 { 144 cli.ShowAppHelpAndExit(c, 0) 145 } 146 147 env := c.String("env") 148 149 required := c.StringSlice("required") 150 required = cnf.MergeRequired(env, required) 151 152 max := c.Int("max-restarts") 153 if c.Bool("forever") { 154 max = math.MaxInt 155 } 156 157 o := envset.RunOptions{ 158 Cmd: ecmd.Cmd, 159 Args: ecmd.Args, 160 Isolated: c.Bool("isolated"), 161 Expand: c.Bool("expand"), 162 Filename: c.String("env-file"), 163 CommentSectionNames: cnf.CommentSectionNames.Keys, 164 Required: required, 165 Inherit: c.StringSlice("inherit"), 166 ExportEnvName: c.String("export-env-name"), 167 Restart: c.Bool("restart"), 168 MaxRestarts: max, 169 } 170 171 //Run if we have something like this: 172 // envset --env-file=.env -- node index.js 173 // envset --env-file=.envset --env=development -- node index.js 174 if ecmd.Cmd != "" && o.Filename != cnf.Filename { 175 return envset.Run(env, o) 176 } 177 178 // envset undefined ==> show error: environment undefined does not exist 179 // envset undefined -- node index.js ==> show error: environment undefined does not exist 180 if c.NArg() >= 1 && !c.Command.HasName(c.Args().First()) { 181 return cli.Exit(fmt.Sprintf("%s: not a valid environment name", c.Args().First()), 1) 182 } 183 184 //we called something like: 185 //envset --env-file=.env 186 //envset --env-file=.envset --env=development 187 return envset.Print(env, o) 188 } 189 190 //TODO: we should process args to remove executable context 191 //and return the arguments that are only for envset 192 err = app.Run(args) 193 if err != nil { 194 fmt.Printf("%s\n", err.Error()) 195 os.Exit(1) 196 } 197 }