github.com/rudderlabs/rudder-go-kit@v0.30.0/testhelper/docker/resource/zipkin/zipkin.go (about)

     1  package zipkin
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"strconv"
     7  	"sync"
     8  
     9  	"github.com/ory/dockertest/v3"
    10  	"github.com/ory/dockertest/v3/docker"
    11  
    12  	"github.com/rudderlabs/rudder-go-kit/httputil"
    13  	"github.com/rudderlabs/rudder-go-kit/testhelper"
    14  	"github.com/rudderlabs/rudder-go-kit/testhelper/docker/resource"
    15  )
    16  
    17  const port = "9411"
    18  
    19  type Resource struct {
    20  	Port string
    21  
    22  	pool     *dockertest.Pool
    23  	resource *dockertest.Resource
    24  	purged   bool
    25  	purgedMu sync.Mutex
    26  }
    27  
    28  func (z *Resource) Purge() error {
    29  	z.purgedMu.Lock()
    30  	defer z.purgedMu.Unlock()
    31  
    32  	if z.purged {
    33  		return nil
    34  	}
    35  
    36  	if err := z.pool.Purge(z.resource); err != nil {
    37  		return err
    38  	}
    39  
    40  	z.purged = true
    41  
    42  	return nil
    43  }
    44  
    45  func Setup(pool *dockertest.Pool, d resource.Cleaner) (*Resource, error) {
    46  	freePort, err := testhelper.GetFreePort()
    47  	if err != nil {
    48  		return nil, fmt.Errorf("failed to get free port: %w", err)
    49  	}
    50  
    51  	zipkin, err := pool.RunWithOptions(&dockertest.RunOptions{
    52  		Repository:   "openzipkin/zipkin",
    53  		ExposedPorts: []string{port},
    54  		PortBindings: map[docker.Port][]docker.PortBinding{
    55  			port + "/tcp": {{HostPort: strconv.Itoa(freePort)}},
    56  		},
    57  	})
    58  	if err != nil {
    59  		return nil, fmt.Errorf("failed to start zipkin: %w", err)
    60  	}
    61  
    62  	res := &Resource{
    63  		pool:     pool,
    64  		resource: zipkin,
    65  		Port:     zipkin.GetPort(port + "/tcp"),
    66  	}
    67  	d.Cleanup(func() {
    68  		if err := res.Purge(); err != nil {
    69  			d.Log("Could not purge zipkin resource:", err)
    70  		}
    71  	})
    72  
    73  	zipkinHealthURL := "http://localhost:" + strconv.Itoa(freePort) + "/health"
    74  	healthReq, err := http.NewRequest(http.MethodGet, zipkinHealthURL, nil)
    75  	if err != nil {
    76  		return nil, fmt.Errorf("failed to create zipkin health request: %w", err)
    77  	}
    78  
    79  	err = pool.Retry(func() error {
    80  		resp, err := http.DefaultClient.Do(healthReq)
    81  		if err != nil {
    82  			return fmt.Errorf("failed to get zipkin health: %w", err)
    83  		}
    84  
    85  		defer func() { httputil.CloseResponse(resp) }()
    86  
    87  		if resp.StatusCode != http.StatusOK {
    88  			return fmt.Errorf("zipkin health returned status code %d", resp.StatusCode)
    89  		}
    90  
    91  		return nil
    92  	})
    93  	if err != nil {
    94  		return nil, fmt.Errorf("failed to wait for zipkin to be ready: %w", err)
    95  	}
    96  
    97  	return res, nil
    98  }