pkg/api/platformapi/allocatorapi/vacate_params.go (136 lines of code) (raw):
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you 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
//
// http://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 allocatorapi
import (
"errors"
"fmt"
"time"
"github.com/elastic/cloud-sdk-go/pkg/api"
"github.com/elastic/cloud-sdk-go/pkg/api/apierror"
"github.com/elastic/cloud-sdk-go/pkg/models"
"github.com/elastic/cloud-sdk-go/pkg/multierror"
"github.com/elastic/cloud-sdk-go/pkg/output"
"github.com/elastic/cloud-sdk-go/pkg/sync/pool"
"github.com/elastic/cloud-sdk-go/pkg/util"
"github.com/elastic/cloud-sdk-go/pkg/util/ec"
"github.com/elastic/cloud-sdk-go/pkg/util/slice"
)
var (
errCannotFilterByIDAndKind = errors.New(`only one of "clusters" or "kind" can be specified`)
errMustSpecifyAtLeast1Allocator = errors.New("must specify at least one allocator")
errAPIMustNotBeNil = errors.New("api must not be nil")
errConcurrencyCannotBeZero = errors.New("concurrency cannot be 0")
errOutputDeviceCannotBeNil = errors.New("output device cannot be nil")
errCannotOverrideAllocatorDown = errors.New("cannot set the AllocatorDown when multiple allocators are specified")
allowedClusterKinds = []string{
util.Apm,
util.Appsearch,
util.Elasticsearch,
util.EnterpriseSearch,
util.Kibana,
}
)
// VacateParams used to vacate N allocators or clusters.
//nolint
type VacateParams struct {
*api.API
Region string
// List of allocators that will be marked to be vacated.
Allocators []string
// List of allocators to be used as potential targets.
PreferredAllocators []string
// Can specify a list of cluster IDs that will be moved
// of N numbers of allocators.
ClusterFilter []string
// If specified it will only move clusters that match the kind
// (elasticsearch, kibana).
KindFilter string
// Maximum number of concurrent cluster moves at any time.
Concurrency uint16
// Output device where the progress will be sent.
Output *output.Device
// OutputFormat to use
OutputFormat string
// Maximum number of errors to allow the plan status poller to tolerate.
MaxPollRetries uint8
// Poll frequency
TrackFrequency time.Duration
// Optional value to be set to the pool on construction.
PoolTimeout pool.Timeout
// Optional value to be set to override the default autodiscovery of an
// allocator's health. This can only be used when a single allocator is
// specified.
AllocatorDown *bool
// Optional value to be set to keep the cluster in its current -possibly broken- state and just does the
// bare minimum to move the requested instances across to another allocator.
MoveOnly *bool
// SkipTracking skips displaying and waiting for the individual vacates to complete.
// Setting it to true will render the concurrency flag pretty much ineffective since
// the vacate action is asynchronous and the only thing keeping the working items in
// the pool is the tracking function call which synchronously waits until the vacate
// has effectively finished.
SkipTracking bool
// Plan body overrides to place in all of the vacate clusters.
PlanOverrides
}
// Validate validates the parameters
func (params VacateParams) Validate() error {
var merr = multierror.NewPrefixed("invalid allocator vacate params")
if params.API == nil {
merr = merr.Append(errAPIMustNotBeNil)
}
if len(params.Allocators) == 0 {
merr = merr.Append(errMustSpecifyAtLeast1Allocator)
}
if len(params.ClusterFilter) > 0 && len(params.KindFilter) > 0 {
merr = merr.Append(errCannotFilterByIDAndKind)
}
if params.Concurrency == 0 {
merr = merr.Append(errConcurrencyCannotBeZero)
}
for i := range params.ClusterFilter {
if len(params.ClusterFilter[i]) != 32 {
merr = merr.Append(fmt.Errorf(
"cluster filter: id \"%s\" is invalid, must be 32 characters long", params.ClusterFilter[i],
))
}
}
if params.Output == nil {
merr = merr.Append(errOutputDeviceCannotBeNil)
}
if params.AllocatorDown != nil && len(params.Allocators) > 1 {
merr = merr.Append(errCannotOverrideAllocatorDown)
}
if err := ec.RequireRegionSet(params.Region); err != nil {
merr = merr.Append(err)
}
return merr.ErrorOrNil()
}
// VacateClusterParams is used by VacateCluster to move a cluster node
// from an allocator.
type VacateClusterParams struct {
PreferredAllocators []string
ClusterFilter []string
// Plan body overrides to place in all of the vacate clusters.
PlanOverrides
Region string
ID string // allocatorID
ClusterID string
Kind string
*api.API
TrackFrequency time.Duration
AllocatorDown *bool
MoveOnly *bool
Output *output.Device
OutputFormat string
MaxPollRetries uint8
SkipTracking bool
}
// Validate validates the parameters
func (params VacateClusterParams) Validate() error {
var merr = multierror.NewPrefixed("invalid allocator vacate params")
if params.API == nil {
merr = merr.Append(apierror.ErrMissingAPI)
}
if params.ID == "" {
merr = merr.Append(
fmt.Errorf("invalid allocator ID %s", params.ID),
)
}
if len(params.ClusterID) != 32 {
merr = merr.Append(
fmt.Errorf("invalid cluster ID %s", params.ClusterID),
)
}
if !slice.HasString(allowedClusterKinds, params.Kind) {
merr = merr.Append(
fmt.Errorf("invalid kind %s", params.Kind),
)
}
if params.Output == nil {
merr = merr.Append(errOutputDeviceCannotBeNil)
}
if err := ec.RequireRegionSet(params.Region); err != nil {
merr = merr.Append(err)
}
return merr.ErrorOrNil()
}
type addAllocatorMovesToPoolParams struct {
ID string
Moves *models.MoveClustersDetails
Pool *pool.Pool
VacateParams *VacateParams
}
// PlanOverrides is used to override any API value that is returned by default
// with the specified value.
type PlanOverrides struct {
// SkipSnapshot overwrites the Transient part of an Elastisearch vacate.
SkipSnapshot *bool
SkipDataMigration *bool
OverrideFailsafe *bool
}