github.com/m3db/m3@v1.5.0/src/cluster/placementhandler/handleroptions/service_options.go (about)

     1  // Copyright (c) 2019 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 handleroptions
    22  
    23  import (
    24  	"errors"
    25  	"net/http"
    26  	"strings"
    27  	"time"
    28  
    29  	"github.com/m3db/m3/src/cluster/kv"
    30  	"github.com/m3db/m3/src/cluster/services"
    31  	"github.com/m3db/m3/src/x/headers"
    32  )
    33  
    34  const (
    35  	// M3DBServiceName is the service name for M3DB.
    36  	M3DBServiceName = "m3db"
    37  	// M3AggregatorServiceName is the service name for M3Aggregator.
    38  	M3AggregatorServiceName = "m3aggregator"
    39  	// M3CoordinatorServiceName is the service name for M3Coordinator.
    40  	M3CoordinatorServiceName = "m3coordinator"
    41  
    42  	defaultM3AggMaxAggregationWindowSize = time.Minute
    43  	// defaultM3AggWarmupDuration configures the buffer to account for the delay
    44  	// of propagating aggregator placement to clients, usually needed when there is
    45  	// a large amount of clients sending traffic to m3aggregator.
    46  	defaultM3AggWarmupDuration = 0
    47  )
    48  
    49  var (
    50  	errServiceNameIsRequired        = errors.New("service name is required")
    51  	errServiceEnvironmentIsRequired = errors.New("service environment is required")
    52  	errServiceZoneIsRequired        = errors.New("service zone is required")
    53  	errM3AggServiceOptionsRequired  = errors.New("m3agg service options are required")
    54  )
    55  
    56  // ServiceOptions are the options for Service.
    57  type ServiceOptions struct {
    58  	ServiceName        string
    59  	ServiceEnvironment string
    60  	ServiceZone        string
    61  
    62  	M3Agg *M3AggServiceOptions
    63  
    64  	DryRun bool
    65  	Force  bool
    66  }
    67  
    68  // M3AggServiceOptions contains the service options that are
    69  // specific to the M3Agg service.
    70  type M3AggServiceOptions struct {
    71  	MaxAggregationWindowSize time.Duration
    72  	WarmupDuration           time.Duration
    73  }
    74  
    75  // ServiceOptionsDefault is a default to apply to service options.
    76  type ServiceOptionsDefault func(o ServiceOptions) ServiceOptions
    77  
    78  // WithDefaultServiceEnvironment returns the default service environment.
    79  func WithDefaultServiceEnvironment(env string) ServiceOptionsDefault {
    80  	return func(o ServiceOptions) ServiceOptions {
    81  		o.ServiceEnvironment = env
    82  		return o
    83  	}
    84  }
    85  
    86  // WithDefaultServiceZone returns the default service zone.
    87  func WithDefaultServiceZone(zone string) ServiceOptionsDefault {
    88  	return func(o ServiceOptions) ServiceOptions {
    89  		o.ServiceZone = zone
    90  		return o
    91  	}
    92  }
    93  
    94  // ServiceNameAndDefaults is the params used when identifying a service
    95  // and it's service option defaults.
    96  type ServiceNameAndDefaults struct {
    97  	ServiceName string
    98  	Defaults    []ServiceOptionsDefault
    99  }
   100  
   101  // NewServiceOptions returns a ServiceOptions based on the provided
   102  // values.
   103  func NewServiceOptions(
   104  	service ServiceNameAndDefaults,
   105  	header http.Header,
   106  	m3AggOpts *M3AggServiceOptions,
   107  ) ServiceOptions {
   108  	opts := ServiceOptions{
   109  		ServiceName:        service.ServiceName,
   110  		ServiceEnvironment: headers.DefaultServiceEnvironment,
   111  		ServiceZone:        headers.DefaultServiceZone,
   112  
   113  		DryRun: false,
   114  		Force:  false,
   115  
   116  		M3Agg: &M3AggServiceOptions{
   117  			MaxAggregationWindowSize: defaultM3AggMaxAggregationWindowSize,
   118  			WarmupDuration:           defaultM3AggWarmupDuration,
   119  		},
   120  	}
   121  	for _, applyDefault := range service.Defaults {
   122  		opts = applyDefault(opts)
   123  	}
   124  
   125  	if v := strings.TrimSpace(header.Get(headers.HeaderClusterEnvironmentName)); v != "" {
   126  		opts.ServiceEnvironment = v
   127  	}
   128  	if v := strings.TrimSpace(header.Get(headers.HeaderClusterZoneName)); v != "" {
   129  		opts.ServiceZone = v
   130  	}
   131  	if v := strings.TrimSpace(header.Get(headers.HeaderDryRun)); v == "true" {
   132  		opts.DryRun = true
   133  	}
   134  	if v := strings.TrimSpace(header.Get(headers.HeaderForce)); v == "true" {
   135  		opts.Force = true
   136  	}
   137  
   138  	if m3AggOpts != nil {
   139  		if m3AggOpts.MaxAggregationWindowSize > 0 {
   140  			opts.M3Agg.MaxAggregationWindowSize = m3AggOpts.MaxAggregationWindowSize
   141  		}
   142  
   143  		if m3AggOpts.WarmupDuration > 0 {
   144  			opts.M3Agg.WarmupDuration = m3AggOpts.WarmupDuration
   145  		}
   146  	}
   147  
   148  	return opts
   149  }
   150  
   151  // Validate ensures the service options are valid.
   152  func (opts *ServiceOptions) Validate() error {
   153  	if opts.ServiceName == "" {
   154  		return errServiceNameIsRequired
   155  	}
   156  	if opts.ServiceEnvironment == "" {
   157  		return errServiceEnvironmentIsRequired
   158  	}
   159  	if opts.ServiceZone == "" {
   160  		return errServiceZoneIsRequired
   161  	}
   162  	if opts.ServiceName == M3AggregatorServiceName && opts.M3Agg == nil {
   163  		return errM3AggServiceOptionsRequired
   164  	}
   165  	return nil
   166  }
   167  
   168  // ServiceID constructs a cluster services ID from the options.
   169  func (opts *ServiceOptions) ServiceID() services.ServiceID {
   170  	return services.NewServiceID().
   171  		SetName(opts.ServiceName).
   172  		SetEnvironment(opts.ServiceEnvironment).
   173  		SetZone(opts.ServiceZone)
   174  }
   175  
   176  // KVOverrideOptions constructs KV overrides from the current service options.
   177  func (opts *ServiceOptions) KVOverrideOptions() kv.OverrideOptions {
   178  	return kv.NewOverrideOptions().
   179  		SetEnvironment(opts.ServiceEnvironment).
   180  		SetZone(opts.ServiceZone)
   181  }