github.com/m3db/m3@v1.5.0/src/integration/resources/docker/coordinator.go (about)

     1  // Copyright (c) 2020 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package docker
    22  
    23  import (
    24  	"errors"
    25  	"fmt"
    26  	"net/http"
    27  	"time"
    28  
    29  	"github.com/ory/dockertest/v3"
    30  	"github.com/prometheus/common/model"
    31  
    32  	"github.com/m3db/m3/src/integration/resources"
    33  	"github.com/m3db/m3/src/query/api/v1/options"
    34  	"github.com/m3db/m3/src/query/generated/proto/admin"
    35  	"github.com/m3db/m3/src/query/generated/proto/prompb"
    36  )
    37  
    38  const (
    39  	defaultCoordinatorSource = "coordinator"
    40  	defaultCoordinatorName   = "coord01"
    41  )
    42  
    43  var (
    44  	defaultCoordinatorList = []int{7201, 7203, 7204}
    45  
    46  	defaultCoordinatorOptions = ResourceOptions{
    47  		Source:        defaultCoordinatorSource,
    48  		ContainerName: defaultCoordinatorName,
    49  		PortList:      defaultCoordinatorList,
    50  	}
    51  )
    52  
    53  type coordinator struct {
    54  	resource *Resource
    55  	client   resources.CoordinatorClient
    56  }
    57  
    58  func newDockerHTTPCoordinator(
    59  	pool *dockertest.Pool,
    60  	opts ResourceOptions,
    61  ) (resources.Coordinator, error) {
    62  	opts = opts.withDefaults(defaultCoordinatorOptions)
    63  	opts.TmpfsMounts = []string{"/etc/m3coordinator/"}
    64  
    65  	resource, err := NewDockerResource(pool, opts)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  
    70  	return &coordinator{
    71  		resource: resource,
    72  		client: resources.NewCoordinatorClient(resources.CoordinatorClientOptions{
    73  			Client:    http.DefaultClient,
    74  			HTTPPort:  7201,
    75  			Logger:    resource.logger,
    76  			RetryFunc: resource.pool.Retry,
    77  		}),
    78  	}, nil
    79  }
    80  
    81  func (c *coordinator) Start() {
    82  	// noop as docker container should already be started
    83  }
    84  
    85  func (c *coordinator) HostDetails() (*resources.InstanceInfo, error) {
    86  	// TODO: add implementation
    87  	return nil, errors.New("not implemented")
    88  }
    89  
    90  func (c *coordinator) GetNamespace() (admin.NamespaceGetResponse, error) {
    91  	if c.resource.closed {
    92  		return admin.NamespaceGetResponse{}, errClosed
    93  	}
    94  
    95  	return c.client.GetNamespace()
    96  }
    97  
    98  func (c *coordinator) GetPlacement(
    99  	opts resources.PlacementRequestOptions,
   100  ) (admin.PlacementGetResponse, error) {
   101  	if c.resource.closed {
   102  		return admin.PlacementGetResponse{}, errClosed
   103  	}
   104  
   105  	return c.client.GetPlacement(opts)
   106  }
   107  
   108  func (c *coordinator) InitPlacement(
   109  	opts resources.PlacementRequestOptions,
   110  	req admin.PlacementInitRequest,
   111  ) (admin.PlacementGetResponse, error) {
   112  	if c.resource.closed {
   113  		return admin.PlacementGetResponse{}, errClosed
   114  	}
   115  
   116  	return c.client.InitPlacement(opts, req)
   117  }
   118  
   119  func (c *coordinator) DeleteAllPlacements(
   120  	opts resources.PlacementRequestOptions,
   121  ) error {
   122  	if c.resource.closed {
   123  		return errClosed
   124  	}
   125  
   126  	return c.client.DeleteAllPlacements(opts)
   127  }
   128  
   129  func (c *coordinator) WaitForNamespace(name string) error {
   130  	if c.resource.closed {
   131  		return errClosed
   132  	}
   133  
   134  	return c.client.WaitForNamespace(name)
   135  }
   136  
   137  func (c *coordinator) WaitForInstances(
   138  	ids []string,
   139  ) error {
   140  	if c.resource.closed {
   141  		return errClosed
   142  	}
   143  
   144  	return c.client.WaitForInstances(ids)
   145  }
   146  
   147  func (c *coordinator) WaitForShardsReady() error {
   148  	if c.resource.closed {
   149  		return errClosed
   150  	}
   151  
   152  	return c.client.WaitForShardsReady()
   153  }
   154  
   155  func (c *coordinator) WaitForClusterReady() error {
   156  	if c.resource.closed {
   157  		return errClosed
   158  	}
   159  
   160  	return c.client.WaitForClusterReady()
   161  }
   162  
   163  func (c *coordinator) CreateDatabase(
   164  	addRequest admin.DatabaseCreateRequest,
   165  ) (admin.DatabaseCreateResponse, error) {
   166  	if c.resource.closed {
   167  		return admin.DatabaseCreateResponse{}, errClosed
   168  	}
   169  
   170  	return c.client.CreateDatabase(addRequest)
   171  }
   172  
   173  func (c *coordinator) AddNamespace(
   174  	addRequest admin.NamespaceAddRequest,
   175  ) (admin.NamespaceGetResponse, error) {
   176  	if c.resource.closed {
   177  		return admin.NamespaceGetResponse{}, errClosed
   178  	}
   179  
   180  	return c.client.AddNamespace(addRequest)
   181  }
   182  
   183  func (c *coordinator) UpdateNamespace(
   184  	req admin.NamespaceUpdateRequest,
   185  ) (admin.NamespaceGetResponse, error) {
   186  	if c.resource.closed {
   187  		return admin.NamespaceGetResponse{}, errClosed
   188  	}
   189  
   190  	return c.client.UpdateNamespace(req)
   191  }
   192  
   193  func (c *coordinator) DeleteNamespace(namespaceID string) error {
   194  	if c.resource.closed {
   195  		return errClosed
   196  	}
   197  
   198  	return c.client.DeleteNamespace(namespaceID)
   199  }
   200  
   201  func (c *coordinator) WriteCarbon(
   202  	port int, metric string, v float64, t time.Time,
   203  ) error {
   204  	if c.resource.closed {
   205  		return errClosed
   206  	}
   207  
   208  	url := c.resource.resource.GetHostPort(fmt.Sprintf("%d/tcp", port))
   209  
   210  	return c.client.WriteCarbon(url, metric, v, t)
   211  }
   212  
   213  func (c *coordinator) WriteProm(
   214  	name string,
   215  	tags map[string]string,
   216  	samples []prompb.Sample,
   217  	headers resources.Headers,
   218  ) error {
   219  	if c.resource.closed {
   220  		return errClosed
   221  	}
   222  
   223  	return c.client.WriteProm(name, tags, samples, headers)
   224  }
   225  
   226  func (c *coordinator) WritePromWithRequest(
   227  	writeRequest prompb.WriteRequest,
   228  	headers resources.Headers,
   229  ) error {
   230  	if c.resource.closed {
   231  		return errClosed
   232  	}
   233  
   234  	return c.client.WritePromWithRequest(writeRequest, headers)
   235  }
   236  
   237  func (c *coordinator) ApplyKVUpdate(update string) error {
   238  	if c.resource.closed {
   239  		return errClosed
   240  	}
   241  
   242  	return c.client.ApplyKVUpdate(update)
   243  }
   244  
   245  func (c *coordinator) RunQuery(
   246  	verifier resources.ResponseVerifier,
   247  	query string,
   248  	headers resources.Headers,
   249  ) error {
   250  	if c.resource.closed {
   251  		return errClosed
   252  	}
   253  
   254  	return c.client.RunQuery(verifier, query, headers)
   255  }
   256  
   257  func (c *coordinator) InstantQuery(
   258  	req resources.QueryRequest,
   259  	headers resources.Headers,
   260  ) (model.Vector, error) {
   261  	if c.resource.closed {
   262  		return nil, errClosed
   263  	}
   264  	return c.client.InstantQuery(req, headers)
   265  }
   266  
   267  // InstantQueryWithEngine runs an instant query with provided headers and the specified
   268  // query engine.
   269  func (c *coordinator) InstantQueryWithEngine(
   270  	req resources.QueryRequest,
   271  	engine options.QueryEngine,
   272  	headers resources.Headers,
   273  ) (model.Vector, error) {
   274  	if c.resource.closed {
   275  		return nil, errClosed
   276  	}
   277  	return c.client.InstantQueryWithEngine(req, engine, headers)
   278  }
   279  
   280  // RangeQuery runs a range query with provided headers
   281  func (c *coordinator) RangeQuery(
   282  	req resources.RangeQueryRequest,
   283  	headers resources.Headers,
   284  ) (model.Matrix, error) {
   285  	if c.resource.closed {
   286  		return nil, errClosed
   287  	}
   288  	return c.client.RangeQuery(req, headers)
   289  }
   290  
   291  // GraphiteQuery retrieves graphite raw data.
   292  func (c *coordinator) GraphiteQuery(req resources.GraphiteQueryRequest) ([]resources.Datapoint, error) {
   293  	return c.client.GraphiteQuery(req)
   294  }
   295  
   296  // RangeQueryWithEngine runs a range query with provided headers and the specified
   297  // query engine.
   298  func (c *coordinator) RangeQueryWithEngine(
   299  	req resources.RangeQueryRequest,
   300  	engine options.QueryEngine,
   301  	headers resources.Headers,
   302  ) (model.Matrix, error) {
   303  	if c.resource.closed {
   304  		return nil, errClosed
   305  	}
   306  	return c.client.RangeQueryWithEngine(req, engine, headers)
   307  }
   308  
   309  // LabelNames return matching label names based on the request.
   310  func (c *coordinator) LabelNames(
   311  	req resources.LabelNamesRequest,
   312  	headers resources.Headers,
   313  ) (model.LabelNames, error) {
   314  	if c.resource.closed {
   315  		return nil, errClosed
   316  	}
   317  	return c.client.LabelNames(req, headers)
   318  }
   319  
   320  // LabelValues returns matching label values based on the request.
   321  func (c *coordinator) LabelValues(
   322  	req resources.LabelValuesRequest,
   323  	headers resources.Headers,
   324  ) (model.LabelValues, error) {
   325  	if c.resource.closed {
   326  		return nil, errClosed
   327  	}
   328  	return c.client.LabelValues(req, headers)
   329  }
   330  
   331  // Series returns matching series based on the request.
   332  func (c *coordinator) Series(
   333  	req resources.SeriesRequest,
   334  	headers resources.Headers,
   335  ) ([]model.Metric, error) {
   336  	if c.resource.closed {
   337  		return nil, errClosed
   338  	}
   339  	return c.client.Series(req, headers)
   340  }
   341  
   342  func (c *coordinator) Close() error {
   343  	if c.resource.closed {
   344  		return errClosed
   345  	}
   346  
   347  	return c.resource.Close()
   348  }
   349  
   350  func (c *coordinator) InitM3msgTopic(
   351  	opts resources.M3msgTopicOptions,
   352  	req admin.TopicInitRequest,
   353  ) (admin.TopicGetResponse, error) {
   354  	return c.client.InitM3msgTopic(opts, req)
   355  }
   356  
   357  func (c *coordinator) GetM3msgTopic(
   358  	opts resources.M3msgTopicOptions,
   359  ) (admin.TopicGetResponse, error) {
   360  	return c.client.GetM3msgTopic(opts)
   361  }
   362  
   363  func (c *coordinator) AddM3msgTopicConsumer(
   364  	opts resources.M3msgTopicOptions,
   365  	req admin.TopicAddRequest,
   366  ) (admin.TopicGetResponse, error) {
   367  	return c.client.AddM3msgTopicConsumer(opts, req)
   368  }