// updates function code, settings in AWS lambda func (d *deployer) updateLambda( l *lambda.Lambda, code *lambda.FunctionCode, iamRole *string, ) error { cfg := d.cfg _, err := l.UpdateFunctionConfiguration( &lambda.UpdateFunctionConfigurationInput{ FunctionName: cfg.Name, Description: cfg.Description, Handler: cfg.EntryPoint, MemorySize: cfg.MemorySize, Role: iamRole, Timeout: cfg.Timeout, }, ) if err != nil { return err } _, err = l.UpdateFunctionCode( &lambda.UpdateFunctionCodeInput{ FunctionName: cfg.Name, S3Bucket: code.S3Bucket, S3Key: code.S3Key, S3ObjectVersion: code.S3ObjectVersion, ZipFile: code.ZipFile, Publish: aws.Bool(true), }, ) if err != nil { return err } return nil }
} return } } if r.HTTPResponse == nil { // Add a dummy request response object to ensure the HTTPResponse // value is consistent. r.HTTPResponse = &http.Response{ StatusCode: int(0), Status: http.StatusText(int(0)), Body: ioutil.NopCloser(bytes.NewReader([]byte{})), } } // Catch all other request errors. r.Error = awserr.New("RequestError", "send request failed", err) r.Retryable = aws.Bool(true) // network errors are retryable } }} // ValidateResponseHandler is a request handler to validate service response. var ValidateResponseHandler = request.NamedHandler{"core.ValidateResponseHandler", func(r *request.Request) { if r.HTTPResponse.StatusCode == 0 || r.HTTPResponse.StatusCode >= 300 { // this may be replaced by an UnmarshalError handler r.Error = awserr.New("UnknownError", "unknown error", nil) } }} // AfterRetryHandler performs final checks to determine if the request should // be retried and how long to delay. var AfterRetryHandler = request.NamedHandler{"core.AfterRetryHandler", func(r *request.Request) { // If one of the other handlers already set the retry state
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 }