e2etestrunner/setuplocal.go (147 lines of code) (raw):

// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package e2etestrunner import ( "context" "fmt" "log" "os" "github.com/GoogleCloudPlatform/opentelemetry-operations-e2e-testing/e2etestrunner/setuptf" "github.com/GoogleCloudPlatform/opentelemetry-operations-e2e-testing/e2etestrunner/testclient" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/mount" "github.com/docker/docker/client" "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/stdcopy" "github.com/docker/go-connections/nat" ) const localTfDir = "tf/local" // Set up the instrumented test server for a local run by running in a docker // container on the local host func SetupLocal( ctx context.Context, args *Args, logger *log.Logger, ) (*testclient.Client, Cleanup, error) { pubsubInfo, cleanupTf, err := setuptf.SetupTf( ctx, args.ProjectID, args.TestRunID, localTfDir, map[string]string{}, logger, ) if err != nil { return nil, cleanupTf, err } cli, err := client.NewClientWithOpts(client.FromEnv) if err != nil { return nil, cleanupTf, err } cli.NegotiateAPIVersion(ctx) createdRes, err := createContainer(ctx, cli, args, pubsubInfo, logger) if err != nil { if errdefs.IsNotFound(err) { err = fmt.Errorf( `docker image not found, try running "docker pull %v": %w`, args.Local.Image, err, ) } return nil, cleanupTf, err } if len(createdRes.Warnings) != 0 { logger.Printf("Started with warnings: %v", createdRes.Warnings) } containerID := createdRes.ID removeContainer := func() { defer cleanupTf() err = cli.ContainerRemove(ctx, containerID, container.RemoveOptions{Force: true}) if err != nil { logger.Panic(err) } } err = cli.ContainerStart(ctx, containerID, container.StartOptions{}) if err != nil { return nil, removeContainer, err } cleanup := func() { logger.Printf("Stopping and removing container ID %v\n", containerID) timeout := 15 err = cli.ContainerStop(ctx, containerID, container.StopOptions{Timeout: &timeout}) defer removeContainer() if err != nil { logger.Panic(err) } } err = startForwardingContainerLogs(ctx, cli, containerID, logger) if err != nil { return nil, cleanup, err } client, err := testclient.New(ctx, args.ProjectID, pubsubInfo) if err != nil { return nil, cleanup, err } return client, cleanup, err } func createContainer( ctx context.Context, cli *client.Client, args *Args, pubsubInfo *setuptf.PubsubInfo, logger *log.Logger, ) (container.CreateResponse, error) { env := []string{ "PORT=" + args.Local.Port, "PROJECT_ID=" + args.ProjectID, "REQUEST_SUBSCRIPTION_NAME=" + pubsubInfo.RequestTopic.SubscriptionName, "RESPONSE_TOPIC_NAME=" + pubsubInfo.ResponseTopic.TopicName, "SUBSCRIPTION_MODE=" + string(setuptf.Pull), } mounts := []mount.Mount{} if args.Local.GoogleApplicationCredentials != "" { env = append(env, "GOOGLE_APPLICATION_CREDENTIALS="+args.Local.GoogleApplicationCredentials) mounts = append(mounts, mount.Mount{ Type: mount.TypeBind, Source: args.Local.GoogleApplicationCredentials, Target: args.Local.GoogleApplicationCredentials, ReadOnly: true, }) } return cli.ContainerCreate( ctx, &container.Config{ Image: args.Local.Image, Env: env, ExposedPorts: nat.PortSet{ nat.Port(args.Local.Port): struct{}{}, }, User: args.Local.ContainerUser, }, &container.HostConfig{ Mounts: mounts, NetworkMode: container.NetworkMode(args.Local.Network), }, nil, nil, "", ) } // forward container logs to stdout/stderr func startForwardingContainerLogs( ctx context.Context, cli *client.Client, containerID string, logger *log.Logger, ) error { reader, err := cli.ContainerLogs( ctx, containerID, container.LogsOptions{ShowStdout: true, ShowStderr: true, Follow: true}, ) if err != nil { return err } go func() { defer reader.Close() if _, err := stdcopy.StdCopy(os.Stdout, os.Stderr, reader); err != nil { logger.Printf("Error while reading logs, %v\n", err) } }() return nil }