Beispiel #1
0
func (infra *Infrastructure) createLambdaFunction(svc *lambda.Lambda, roleArn string, payload []byte) error {
	function, err := svc.CreateFunction(&lambda.CreateFunctionInput{
		Code: &lambda.FunctionCode{
			ZipFile: payload,
		},
		FunctionName: aws.String("goad"),
		Handler:      aws.String("index.handler"),
		Role:         aws.String(roleArn),
		Runtime:      aws.String("nodejs"),
		MemorySize:   aws.Int64(1536),
		Publish:      aws.Bool(true),
		Timeout:      aws.Int64(300),
	})
	if err != nil {
		if awsErr, ok := err.(awserr.Error); ok {
			// Calling this function too soon after creating the role might
			// fail, so we should retry after a little while.
			// TODO: limit the number of retries.
			if awsErr.Code() == "InvalidParameterValueException" {
				time.Sleep(time.Second)
				return infra.createLambdaFunction(svc, roleArn, payload)
			}
		}
		return err
	}
	return createLambdaAlias(svc, function.Version)
}
func lambdaPermissionExists(rs *terraform.ResourceState, conn *lambda.Lambda) (*LambdaPolicyStatement, error) {
	params := &lambda.GetPolicyInput{
		FunctionName: aws.String(rs.Primary.Attributes["function_name"]),
	}
	if v, ok := rs.Primary.Attributes["qualifier"]; ok {
		params.Qualifier = aws.String(v)
	}

	resp, err := conn.GetPolicy(params)
	if err != nil {
		return nil, fmt.Errorf("Lambda policy not found: %q", err)
	}

	if resp.Policy == nil {
		return nil, fmt.Errorf("Received Lambda policy is empty")
	}

	policyInBytes := []byte(*resp.Policy)
	policy := LambdaPolicy{}
	err = json.Unmarshal(policyInBytes, &policy)
	if err != nil {
		return nil, fmt.Errorf("Error unmarshalling Lambda policy: %s", err)
	}

	return findLambdaPolicyStatementById(&policy, rs.Primary.ID)
}
Beispiel #3
0
func createLambdaAlias(svc *lambda.Lambda, functionVersion *string) error {
	_, err := svc.CreateAlias(&lambda.CreateAliasInput{
		FunctionName:    aws.String("goad"),
		FunctionVersion: functionVersion,
		Name:            aws.String(version.LambdaVersion()),
	})
	return err
}
Beispiel #4
0
func (infra *Infrastructure) updateLambdaFunction(svc *lambda.Lambda, roleArn string, payload []byte) error {
	function, err := svc.UpdateFunctionCode(&lambda.UpdateFunctionCodeInput{
		ZipFile:      payload,
		FunctionName: aws.String("goad"),
		Publish:      aws.Bool(true),
	})
	if err != nil {
		return err
	}
	return createLambdaAlias(svc, function.Version)
}
func listVersionsByFunctionPages(c *lambda.Lambda, input *lambda.ListVersionsByFunctionInput,
	fn func(p *lambda.ListVersionsByFunctionOutput, lastPage bool) bool) error {
	for {
		page, err := c.ListVersionsByFunction(input)
		if err != nil {
			return err
		}
		lastPage := page.NextMarker == nil

		shouldContinue := fn(page, lastPage)
		if !shouldContinue || lastPage {
			break
		}
	}
	return nil
}
Beispiel #6
0
func lambdaExists(svc *lambda.Lambda) (bool, error) {
	_, err := svc.GetFunction(&lambda.GetFunctionInput{
		FunctionName: aws.String("goad"),
	})

	if err != nil {
		if awsErr, ok := err.(awserr.Error); ok {
			if awsErr.Code() == "ResourceNotFoundException" {
				return false, nil
			}
		}
		return false, err
	}

	return true, nil
}
func isLambdaPermissionGone(rs *terraform.ResourceState, conn *lambda.Lambda) error {
	params := &lambda.GetPolicyInput{
		FunctionName: aws.String(rs.Primary.Attributes["function_name"]),
	}
	if v, ok := rs.Primary.Attributes["qualifier"]; ok {
		params.Qualifier = aws.String(v)
	}

	resp, err := conn.GetPolicy(params)
	if awsErr, ok := err.(awserr.Error); ok {
		if awsErr.Code() == "ResourceNotFoundException" {
			// no policy found => all statements deleted
			return nil
		}
	}
	if err != nil {
		return fmt.Errorf("Unexpected error when checking existence of Lambda permission: %s\n%s",
			rs.Primary.ID, err)
	}

	policyInBytes := []byte(*resp.Policy)
	policy := LambdaPolicy{}
	err = json.Unmarshal(policyInBytes, &policy)
	if err != nil {
		return fmt.Errorf("Error unmarshalling Lambda policy (%s): %s", *resp.Policy, err)
	}

	state, err := findLambdaPolicyStatementById(&policy, rs.Primary.ID)
	if err != nil {
		// statement not found => deleted
		return nil
	}

	return fmt.Errorf("Policy statement expected to be gone (%s):\n%s",
		rs.Primary.ID, *state)
}
Beispiel #8
0
func createLambdaFunction(l *lambda.Lambda, code []byte, runtime, role, name, handler string, timeout int) error {
	func_input := &lambda.CreateFunctionInput{
		Code:         &lambda.FunctionCode{ZipFile: code},
		Runtime:      aws.String(runtime),
		Role:         aws.String(role),
		FunctionName: aws.String(name),
		Handler:      aws.String(handler),
		Timeout:      aws.Int64(int64(timeout)),
	}

	resp, err := l.CreateFunction(func_input)
	if err != nil {
		if err.(awserr.Error).Code() == "ResourceConflictException" {
			log.Println("Function already exists, trying to update code")
			input := &lambda.UpdateFunctionCodeInput{
				FunctionName: aws.String(name),
				ZipFile:      code,
			}

			resp, err = l.UpdateFunctionCode(input)
			if err != nil {
				log.Println("Could not update function code", err)
				return err
			}

			configInput := &lambda.UpdateFunctionConfigurationInput{
				FunctionName: aws.String(name),
				Handler:      aws.String(handler),
				Timeout:      aws.Int64(int64(timeout)),
			}
			resp, err = l.UpdateFunctionConfiguration(configInput)
			if err != nil {
				log.Println("Could not update function configuration", err)
				return err
			}

		} else {
			return err
		}
	}

	log.Println(resp)
	return nil
}
Beispiel #9
0
//Returns a result and a debug channels. The channels are closed on test run finalization
func runOnLambda(l *lambda.Lambda, cw *cloudwatchlogs.CloudWatchLogs, test *util.TestDescription) (<-chan string, <-chan string) {
	result := make(chan string, 1)
	debug := make(chan string, 1)
	go func() {
		defer close(result)
		defer close(debug)

		name := test.Name

		debug <- "Getting old log"
		old_invocation_log, err := getLog(cw, name)
		if err != nil {
			old_invocation_log = ""
		}

		payload, _ := json.Marshal(test.Event)

		invoke_input := &lambda.InvokeInput{
			FunctionName:   aws.String(name),
			InvocationType: aws.String("Event"),
			Payload:        payload,
		}
		debug <- "Enqueuing task"
		_, err = l.Invoke(invoke_input)
		if err != nil {
			debug <- fmt.Sprintf("Error invoking function %s ", err)
			return
		}

		timeout := time.Duration(test.Timeout) * time.Second

		debug <- "Waiting for task"
		now := time.Now()
		elapsed := time.After(timeout)
		ticker := time.NewTicker(3 * time.Second)
		defer ticker.Stop()

		log := ""
		completed := false
		requestId := ""
		logGetter := func() (string, error) {
			return getLog(cw, name)
		}

		// waiting for test.Timeout or for the full log whichever occurs first
	logWaitLoop:
		for {
			select {
			case <-elapsed:
				break logWaitLoop
			case <-ticker.C:
				log, requestId, completed, err = getLogAndDetectRequestComplete(logGetter, old_invocation_log, requestId)
				if err != nil {
					debug <- fmt.Sprintf("Error getting log %s ", err)
					return
				}
				if completed {
					break logWaitLoop
				}
			}
		}

		if !completed {
			log, requestId, completed, err = getLogAndDetectRequestComplete(logGetter, old_invocation_log, requestId)
			if err != nil {
				debug <- fmt.Sprintf("Error getting log %s ", err)
				return
			}
			if !completed {
				if requestId != "" {
					debug <- fmt.Sprintf("Request Id: %s", requestId)
				}
				debug <- time.Now().Sub(now).String()
				logLines := strings.Split(log, "\n")
				switch len(logLines) {
				case 0:
					debug <- "Log for current test run is empty"
				case 1:
					debug <- fmt.Sprintf("Log does not contain entries for current test run:\n%s", logLines[0])
				default:
					debug <- fmt.Sprintf("Log does not contain entries for current test run:\n%s\n...\n%s", logLines[0], logLines[len(logLines)-1])
				}
				return
			}
		}
		debug <- fmt.Sprintf("Request Id: %s", requestId)
		final, err := cleanLambda(log)

		if err != nil {
			debug <- fmt.Sprintf("Error cleaning log  %s", err)
			return
		}

		result <- final
	}()
	return result, debug
}