// 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 }
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) } }