// cobra command for creating project func createProjectCmd(c *cobra.Command, args []string) error { if len(args) == 0 || args[0] == "" { return fmt.Errorf("You didn't give us a project name! Please give us one.") } pName := args[0] pCfg, err := getProject(pName) if err != nil { fmt.Printf("Error creating or opening project:\n%s\n", err) return nil } // add the current function to the project if cfg != nil { pCfg.addFunction(cfg) cfg.addProject(pName) err = cfg.writeToFile(cfg.fName) if err != nil { fmt.Printf("Error updating config with project:\n%s\n", err) return nil } } err = pCfg.writeToFile() if err != nil { fmt.Printf("Error saving project:\n%s\n", err) return nil } var action string switch c.Name() { case "add": action = fmt.Sprintf("added %s to", *cfg.Name) default: action = "created" } fmt.Printf("%s project %s\n", action, pName) return nil }
// based on whatever has been passed in, this will determine the // filename for the archive func getArchiveName(c *cobra.Command, cfg *Config) string { var binName string if cfg != nil { binName = *cfg.Name } flagName, _ := c.Flags().GetString("output") if flagName != "" { binName = flagName } if binName == "" { binName = "lambda-phage-" + cuid.New() } // add ".zip" to the filename if one is not found if strings.Index(binName, ".zip") != (len(binName) - 4) { binName += ".zip" } return binName }
// helps you build a config file func initPhage(c *cobra.Command, _ []string) { var err error fmt.Println(` HELLO AND WELCOME This command will help you set up your code for deployment to Lambda! But we need some information from you, like what you want to name your function and a few other things! Please answer the prompts as they appear below: `) iCfg := new(Config) iCfg.IamRole = new(IamRole) iCfg.Location = new(Location) prompts := getPrompts(iCfg) err = prompts.run() // merge in any existing properties from the config object var wCfg *Config if cfg != nil { // if there's a config object, merge these two together cfg.merge(iCfg) wCfg = cfg } else { wCfg = iCfg } cfgFile, _ := c.Flags().GetString("config") err = wCfg.writeToFile(cfgFile) if err != nil { panic(err) } fmt.Printf("Setup complete; saved config to %s\n", cfgFile) }
// packages your package up into a zip file func (p *packager) pkg(c *cobra.Command, _ []string) error { var err error debug := debug.Debug("cmd.pkg") fmt.Println("Adding files to ZIP archive...") binName := getArchiveName(c, cfg) zFile, err := newZipFile(binName) if err != nil { return zipFileFail(err) } wd, err := os.Getwd() if err != nil { return fmt.Errorf("Error opening directory, %s", wd) } root, err := os.Open(".") if err != nil { return fmt.Errorf("Error opening directory, %s", wd) } var infoCh chan string verbose, _ := c.Flags().GetBool("verbose") if verbose { infoCh = make(chan string, 1000) } doneCh := make(chan error) go func() { err := zFile.AddDirectory(root, infoCh) if err != nil { doneCh <- err return } if infoCh != nil { close(infoCh) } doneCh <- nil }() good := true for good { select { case i := <-infoCh: if i != "" { fmt.Println(i) } case e := <-doneCh: if e != nil { debug("errored") return e } good = false } } return zFile.Close() }
func (d *deployer) deploy(c *cobra.Command, args []string) error { debug := debug.Debug("cmd.deploy") // must package first, so: var err error if d.cfg == nil { return fmt.Errorf( `No configuration file found, and you must have one to deploy! Try running lambda-phage init before deploying. `) } fmt.Printf("Beginning deploy of lambda function %s\n", *d.cfg.Name) skipPkg, _ := c.Flags().GetBool("skip-archive") if !skipPkg { pkgEr := packager{ cfg, } err = pkgEr.pkg(c, args) if err != nil { return err } } // should have written data to this file binName := getArchiveName(c, d.cfg) var iamRole *string iamRole, err = cfg.getRoleArn() if err != nil { return err } code := &lambda.FunctionCode{} // try getting s3 information bucket, key := cfg.getS3Info(binName) if bucket == nil || key == nil { fmt.Printf("Will upload archive %s to Lambda\n", binName) // if we couldn't get bucket or // key info, let's upload the data // ...soon b, err := ioutil.ReadFile(binName) if err != nil { return err } code.ZipFile = b } else { fmt.Printf("Will upload archive %s to s3\n", binName) code.S3Bucket = bucket code.S3Key = key err = d.uploadS3(binName, bucket, key) if err != nil { return err } } debug("preparing for lambda API") for _, region := range cfg.Regions { fmt.Printf("Deploying lambda function for %s\n", *region) l := lambda.New( aws.NewConfig(). WithRegion(*region), ) //just try creating the function now _, err := l.CreateFunction( &lambda.CreateFunctionInput{ Code: code, FunctionName: cfg.Name, Description: cfg.Description, Handler: cfg.EntryPoint, MemorySize: cfg.MemorySize, Runtime: cfg.Runtime, Timeout: cfg.Timeout, Role: iamRole, Publish: aws.Bool(true), }, ) if err != nil { if awe, ok := err.(awserr.Error); ok { if awe.Code() == "ResourceConflictException" { debug("function already exists, calling update") err = d.updateLambda(l, code, iamRole) } else { return err } } else { return err } } else { // if the create function succeeded, // we need to figure out the mapping // info, etc debug("function creation succeeded! ...we think") } if err != nil { return err } fmt.Printf("Function %s deployed to region %s!\n", *cfg.Name, *region) } return nil }
// deploys an optionally-filtered set of lambda functions // for the project(s) you specify func deployProjectCmd(c *cobra.Command, args []string) error { debug := debug.Debug("cmd.deployProjectCmd") if len(args) == 0 { fmt.Println("Need to have at least one project name to deploy :( Please type one.") return nil } isDryRun, _ := c.Flags().GetBool("dry-run") filter, _ := c.Flags().GetString("filter") reg, err := regexp.Compile(filter) if err != nil { return fmt.Errorf("Invalid filter, %s\n", err) } for _, prj := range args { pCfg, err := getProject(prj) if err != nil { fmt.Printf("Error loading project %s:\n%s\n", prj, err) } else if pCfg.fromFile == true { for _, f := range pCfg.Functions { cfg, err := loadConfig(f.Path) if err != nil { fmt.Printf( "Error loading config for function %s in project %s:\n%s\n", f.Config.Name, prj, err, ) continue } if reg != nil && !reg.MatchString(*cfg.Name) { // skip current project if it doesn't match regex continue } if isDryRun { fmt.Printf( "Would deploy function %s in project %s\n", *cfg.Name, prj, ) continue } // if loading config succeeded, deploy this thing d := deployer{cfg} err = d.deploy(c, args) if err != nil { fmt.Printf( "Deploy failed for function %s in project %s:\n%s\n", f.Config.Name, prj, err, ) } } } else { debug("skipped project %s because it wasn't found", prj) } } return nil }