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  }