Example #1
0
// Registers public docker image named `imageNameVersion` as a IronWorker called `imageName`.
// For example,
//	  RegisterWithIron("foo/myimage:1", credentials.NewEnvCredentials()) will register a worker called "foo/myimage" that will use Docker Image "foo/myimage:1".
func RegisterWithIron(imageNameVersion string) error {
	tokens := strings.Split(imageNameVersion, ":")
	if len(tokens) != 2 || tokens[0] == "" || tokens[1] == "" {
		return errors.New("Invalid image name. Should be of the form \"name:version\".")
	}

	imageName := tokens[0]

	// Worker API doesn't have support for register yet, but we use it to extract the configuration.
	w := worker.New()
	url := fmt.Sprintf("https://%s/2/projects/%s/codes?oauth=%s", w.Settings.Host, w.Settings.ProjectId, w.Settings.Token)
	registerOpts := map[string]interface{}{
		"name":  imageName,
		"image": imageNameVersion,
		"env_vars": map[string]string{
			"AWS_LAMBDA_FUNCTION_NAME":    imageName,
			"AWS_LAMBDA_FUNCTION_VERSION": "1", // FIXME: swapi does not allow $ right now.
		},
	}

	// Try to forward AWS credentials.
	{
		creds := credentials.NewEnvCredentials()
		v, err := creds.Get()
		if err == nil {
			registerOpts["env_vars"].(map[string]string)["AWS_ACCESS_KEY_ID"] = v.AccessKeyID
			registerOpts["env_vars"].(map[string]string)["AWS_SECRET_ACCESS_KEY"] = v.SecretAccessKey
		}
	}

	marshal, err := json.Marshal(registerOpts)
	var body bytes.Buffer
	mw := multipart.NewWriter(&body)
	jsonWriter, err := mw.CreateFormField("data")
	if err != nil {
		log.Fatalf("This should never fail")
	}
	jsonWriter.Write(marshal)
	mw.Close()

	resp, err := http.Post(url, mw.FormDataContentType(), &body)
	if err == nil {
		b, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return fmt.Errorf("%s readall %s", imageName, err)
		}
		log.Println("Register", imageName, "with iron, response:", string(b))
	}
	return err
}
Example #2
0
func main() {
	helpRequested := flag.Bool("h", false, "Show help")
	flag.Parse()
	if *helpRequested {
		fmt.Fprintln(os.Stderr, `Usage: ./lambda-test-suite [filter]
Runs all tests. If filter is passed, only runs tests matching filter. Filter is applied to entire path relative to tests/ directory.`)
		return
	}

	var filter string
	if flag.NArg() > 0 {
		filter = flag.Arg(0)
	}

	// Verify iron and aws connections.
	w := worker.New()
	_, err := w.TaskList()
	if err != nil {
		log.Fatal("Could not connect to iron.io API", err)
	}

	s := session.New(&aws.Config{Region: aws.String("us-east-1"), Credentials: credentials.NewEnvCredentials()})

	l := lambda.New(s)
	_, err = l.ListFunctions(&lambda.ListFunctionsInput{})
	if err != nil {
		log.Fatal("Could not connect to Lambda API", err)
	}

	cw := cloudwatchlogs.New(s)
	_, err = cw.DescribeLogGroups(&cloudwatchlogs.DescribeLogGroupsInput{})
	if err != nil {
		log.Fatal("Could not connect to CloudWatch API", err)
	}

	log.Print("All API connections successful.")

	tests, err := loadTests(filter)
	if err != nil {
		log.Fatal(err)
	}
	if len(tests) == 0 {
		log.Fatal("No tests to run")
	}

	// expected duration for all tests to run in a sequential way
	// after the fullTimeout expires no test result is accepted and `Timeout` message is reported for a test
	fullTimeout := 0
	for _, test := range tests {
		fullTimeout += test.Timeout + 5
	}

	concurrency := util.NewSemaphore(5) // using a limit, otherwise AWS fails with `ThrottlingException: Rate exceeded` on log retrieval

	endOfTime := time.Now().Add(time.Duration(fullTimeout) * time.Second)
	var testResults <-chan []string = nil
	for _, test := range tests {
		r := runTest(test, w, cw, l, endOfTime, concurrency)

		// forwarding messages from all tests to a single channel
		testResults = util.JoinChannels(testResults, r)
	}

	passed, failed := make([]string, 0, len(tests)), make([]string, 0, len(tests))

	for {
		lines, ok := <-testResults
		if !ok {
			break
		}

		if len(lines) > 0 {
			if strings.HasPrefix(lines[0], "PASS ") {
				passed = append(passed, lines[0])
			}
			if strings.HasPrefix(lines[0], "FAIL ") {
				failed = append(failed, lines[0])
			}
		}

		for _, line := range lines {
			log.Println(line)
		}
	}

	log.Println(fmt.Sprintf("Total %d passed and %d failed tests", len(passed), len(failed)))
	for _, line := range passed {
		log.Println(line)
	}
	for _, line := range failed {
		log.Println(line)
	}

	if len(failed) > 0 {
		os.Exit(1)
	}
}