func (s DeploymentSpec) IsDevelopment() bool {
	return s.GetEnvironment() == EnvironmentDevelopment
}
IsDevelopment returns true when the spec contains a Development environment.
package v2alpha1
import (
	"crypto/sha256"
	"encoding/json"
	"fmt"
	"reflect"
	"github.com/arangodb/kube-arangodb/pkg/util/errors"
	"github.com/arangodb/kube-arangodb/pkg/util"
	core "k8s.io/api/core/v1"
)
var (
	DefaultImage = "arangodb/arangodb:latest"
)
func validatePullPolicy(v core.PullPolicy) error {
	switch v {
	case "", core.PullAlways, core.PullNever, core.PullIfNotPresent:
		return nil
	default:
		return errors.WithStack(errors.Wrapf(ValidationError, "Unknown pull policy: '%s'", string(v)))
	}
}
type DeploymentCommunicationMethod string
func (d *DeploymentCommunicationMethod) Get() DeploymentCommunicationMethod {
	if d == nil {
		return DefaultDeploymentCommunicationMethod
	}
	switch v := *d; v {
	case DeploymentCommunicationMethodHeadlessService, DeploymentCommunicationMethodDNS, DeploymentCommunicationMethodIP, DeploymentCommunicationMethodShortDNS:
		return v
	default:
		return DefaultDeploymentCommunicationMethod
	}
}
func (d DeploymentCommunicationMethod) String() string {
	return string(d)
}
func (d DeploymentCommunicationMethod) New() *DeploymentCommunicationMethod {
	return &d
}
const (
	DefaultDeploymentCommunicationMethod = DeploymentCommunicationMethodHeadlessService
	DeploymentCommunicationMethodHeadlessService DeploymentCommunicationMethod = "headless"
	DeploymentCommunicationMethodDNS DeploymentCommunicationMethod = "dns"
	DeploymentCommunicationMethodShortDNS DeploymentCommunicationMethod = "short-dns"
	DeploymentCommunicationMethodIP DeploymentCommunicationMethod = "ip"
)
type DeploymentSpec struct {
	Mode               *DeploymentMode                   `json:"mode,omitempty"`
	Environment        *Environment                      `json:"environment,omitempty"`
	StorageEngine      *StorageEngine                    `json:"storageEngine,omitempty"`
	Image              *string                           `json:"image,omitempty"`
	ImagePullPolicy    *core.PullPolicy                  `json:"imagePullPolicy,omitempty"`
	ImagePullSecrets   []string                          `json:"imagePullSecrets,omitempty"`
	ImageDiscoveryMode *DeploymentImageDiscoveryModeSpec `json:"imageDiscoveryMode,omitempty"`
	DowntimeAllowed    *bool                             `json:"downtimeAllowed,omitempty"`
	DisableIPv6        *bool                             `json:"disableIPv6,omitempty"`
	Upgrade *DeploymentUpgradeSpec `json:"upgrade,omitempty"`
	Features *DeploymentFeatures `json:"features,omitempty"`
	NetworkAttachedVolumes *bool `json:"networkAttachedVolumes,omitempty"`
	Annotations map[string]string `json:"annotations,omitempty"`
	AnnotationsIgnoreList []string `json:"annotationsIgnoreList,omitempty"`
	AnnotationsMode *LabelsMode `json:"annotationsMode,omitempty"`
	Labels map[string]string `json:"labels,omitempty"`
	LabelsIgnoreList []string `json:"labelsIgnoreList,omitempty"`
	LabelsMode *LabelsMode `json:"labelsMode,omitempty"`
	RestoreFrom *string `json:"restoreFrom,omitempty"`
	RestoreEncryptionSecret *string `json:"restoreEncryptionSecret,omitempty"`
	AllowUnsafeUpgrade *bool `json:"allowUnsafeUpgrade,omitempty"`
	ExternalAccess ExternalAccessSpec `json:"externalAccess"`
	RocksDB        RocksDBSpec        `json:"rocksdb"`
	Authentication AuthenticationSpec `json:"auth"`
	TLS            TLSSpec            `json:"tls"`
	Sync           SyncSpec           `json:"sync"`
	License        LicenseSpec        `json:"license"`
	Metrics        MetricsSpec        `json:"metrics"`
	Lifecycle      LifecycleSpec      `json:"lifecycle,omitempty"`
	ID *ServerIDGroupSpec `json:"id,omitempty"`
	Database *DatabaseSpec `json:"database,omitempty"`
	Single       ServerGroupSpec `json:"single"`
	Agents       ServerGroupSpec `json:"agents"`
	DBServers    ServerGroupSpec `json:"dbservers"`
	Coordinators ServerGroupSpec `json:"coordinators"`
	SyncMasters  ServerGroupSpec `json:"syncmasters"`
	SyncWorkers  ServerGroupSpec `json:"syncworkers"`
	MemberPropagationMode *DeploymentMemberPropagationMode `json:"memberPropagationMode,omitempty"`
	Chaos ChaosSpec `json:"chaos"`
	Recovery *ArangoDeploymentRecoverySpec `json:"recovery,omitempty"`
	Bootstrap BootstrapSpec `json:"bootstrap,omitempty"`
	Timeouts *Timeouts `json:"timeouts,omitempty"`
	ClusterDomain *string `json:"ClusterDomain,omitempty"`
	CommunicationMethod *DeploymentCommunicationMethod `json:"communicationMethod,omitempty"`
	Topology *TopologySpec `json:"topology,omitempty"`
}
func (s *DeploymentSpec) GetAllowMemberRecreation(group ServerGroup) bool {
	if s == nil {
		return false
	}
	groupSpec := s.GetServerGroupSpec(group)
	switch group {
	case ServerGroupDBServers, ServerGroupCoordinators, ServerGroupSyncMasters, ServerGroupSyncWorkers:
		if v := groupSpec.AllowMemberRecreation; v == nil {
			return true
		} else {
			return *v
		}
	default:
		return false
	}
}
func (s *DeploymentSpec) GetRestoreFrom() string {
	return util.StringOrDefault(s.RestoreFrom)
}
func (s *DeploymentSpec) HasRestoreFrom() bool {
	return s.RestoreFrom != nil
}
func (s *DeploymentSpec) Equal(other *DeploymentSpec) bool {
	return reflect.DeepEqual(s, other)
}
func (s DeploymentSpec) GetMode() DeploymentMode {
	return ModeOrDefault(s.Mode)
}
func (s DeploymentSpec) GetEnvironment() Environment {
	return EnvironmentOrDefault(s.Environment)
}
func (s DeploymentSpec) GetAnnotations() map[string]string {
	return s.Annotations
}
func (s DeploymentSpec) GetStorageEngine() StorageEngine {
	return StorageEngineOrDefault(s.StorageEngine)
}
func (s DeploymentSpec) GetImage() string {
	return util.StringOrDefault(s.Image)
}
func (s DeploymentSpec) GetSyncImage() string {
	if s.Sync.HasSyncImage() {
		return s.Sync.GetSyncImage()
	}
	return s.GetImage()
}
func (s DeploymentSpec) GetImagePullPolicy() core.PullPolicy {
	return util.PullPolicyOrDefault(s.ImagePullPolicy)
}
func (s DeploymentSpec) IsDowntimeAllowed() bool {
	return util.BoolOrDefault(s.DowntimeAllowed)
}
func (s DeploymentSpec) IsDisableIPv6() bool {
	return util.BoolOrDefault(s.DisableIPv6)
}
func (s DeploymentSpec) IsNetworkAttachedVolumes() bool {
	return util.BoolOrDefault(s.NetworkAttachedVolumes, false)
}
func (s DeploymentSpec) GetListenAddr() string {
	if s.IsDisableIPv6() {
		return "0.0.0.0"
	}
	return "[::]"
}
func (s DeploymentSpec) IsAuthenticated() bool {
	return s.Authentication.IsAuthenticated()
}
func (s DeploymentSpec) IsSecure() bool {
	return s.TLS.IsSecure()
}
func (s DeploymentSpec) GetServerGroupSpec(group ServerGroup) ServerGroupSpec {
	switch group {
	case ServerGroupSingle:
		return s.Single
	case ServerGroupAgents:
		return s.Agents
	case ServerGroupDBServers:
		return s.DBServers
	case ServerGroupCoordinators:
		return s.Coordinators
	case ServerGroupSyncMasters:
		return s.SyncMasters
	case ServerGroupSyncWorkers:
		return s.SyncWorkers
	default:
		return ServerGroupSpec{}
	}
}
func (s *DeploymentSpec) UpdateServerGroupSpec(group ServerGroup, gspec ServerGroupSpec) {
	switch group {
	case ServerGroupSingle:
		s.Single = gspec
	case ServerGroupAgents:
		s.Agents = gspec
	case ServerGroupDBServers:
		s.DBServers = gspec
	case ServerGroupCoordinators:
		s.Coordinators = gspec
	case ServerGroupSyncMasters:
		s.SyncMasters = gspec
	case ServerGroupSyncWorkers:
		s.SyncWorkers = gspec
	}
}
func (s *DeploymentSpec) SetDefaults(deploymentName string) {
	if s.GetMode() == "" {
		s.Mode = NewMode(DeploymentModeCluster)
	}
	if s.GetEnvironment() == "" {
		s.Environment = NewEnvironment(EnvironmentDevelopment)
	}
	if s.GetStorageEngine() == "" {
		s.StorageEngine = NewStorageEngine(StorageEngineRocksDB)
	}
	if s.GetImage() == "" && s.IsDevelopment() {
		s.Image = util.NewString(DefaultImage)
	}
	if s.GetImagePullPolicy() == "" {
		s.ImagePullPolicy = util.NewPullPolicy(core.PullIfNotPresent)
	}
	s.ExternalAccess.SetDefaults()
	s.RocksDB.SetDefaults()
	s.Authentication.SetDefaults(deploymentName + "-jwt")
	s.TLS.SetDefaults(deploymentName + "-ca")
	s.Sync.SetDefaults(deploymentName+"-sync-jwt", deploymentName+"-sync-client-auth-ca", deploymentName+"-sync-ca", deploymentName+"-sync-mt")
	s.Single.SetDefaults(ServerGroupSingle, s.GetMode().HasSingleServers(), s.GetMode())
	s.Agents.SetDefaults(ServerGroupAgents, s.GetMode().HasAgents(), s.GetMode())
	s.DBServers.SetDefaults(ServerGroupDBServers, s.GetMode().HasDBServers(), s.GetMode())
	s.Coordinators.SetDefaults(ServerGroupCoordinators, s.GetMode().HasCoordinators(), s.GetMode())
	s.SyncMasters.SetDefaults(ServerGroupSyncMasters, s.Sync.IsEnabled(), s.GetMode())
	s.SyncWorkers.SetDefaults(ServerGroupSyncWorkers, s.Sync.IsEnabled(), s.GetMode())
	s.Metrics.SetDefaults(deploymentName+"-exporter-jwt-token", s.Authentication.IsAuthenticated())
	s.Chaos.SetDefaults()
	s.Bootstrap.SetDefaults(deploymentName)
}
func (s *DeploymentSpec) SetDefaultsFrom(source DeploymentSpec) {
	if s.Mode == nil {
		s.Mode = NewModeOrNil(source.Mode)
	}
	if s.Environment == nil {
		s.Environment = NewEnvironmentOrNil(source.Environment)
	}
	if s.StorageEngine == nil {
		s.StorageEngine = NewStorageEngineOrNil(source.StorageEngine)
	}
	if s.Image == nil {
		s.Image = util.NewStringOrNil(source.Image)
	}
	if s.ImagePullPolicy == nil {
		s.ImagePullPolicy = util.NewPullPolicyOrNil(source.ImagePullPolicy)
	}
	if s.DowntimeAllowed == nil {
		s.DowntimeAllowed = util.NewBoolOrNil(source.DowntimeAllowed)
	}
	if s.DisableIPv6 == nil {
		s.DisableIPv6 = util.NewBoolOrNil(source.DisableIPv6)
	}
	if s.AllowUnsafeUpgrade == nil {
		s.AllowUnsafeUpgrade = util.NewBoolOrNil(source.AllowUnsafeUpgrade)
	}
	if s.Database == nil {
		s.Database = source.Database.DeepCopy()
	}
	s.License.SetDefaultsFrom(source.License)
	s.ExternalAccess.SetDefaultsFrom(source.ExternalAccess)
	s.RocksDB.SetDefaultsFrom(source.RocksDB)
	s.Authentication.SetDefaultsFrom(source.Authentication)
	s.TLS.SetDefaultsFrom(source.TLS)
	s.Sync.SetDefaultsFrom(source.Sync)
	s.Single.SetDefaultsFrom(source.Single)
	s.Agents.SetDefaultsFrom(source.Agents)
	s.DBServers.SetDefaultsFrom(source.DBServers)
	s.Coordinators.SetDefaultsFrom(source.Coordinators)
	s.SyncMasters.SetDefaultsFrom(source.SyncMasters)
	s.SyncWorkers.SetDefaultsFrom(source.SyncWorkers)
	s.Metrics.SetDefaultsFrom(source.Metrics)
	s.Lifecycle.SetDefaultsFrom(source.Lifecycle)
	s.Chaos.SetDefaultsFrom(source.Chaos)
	s.Bootstrap.SetDefaultsFrom(source.Bootstrap)
}
func (s *DeploymentSpec) Validate() error {
	if err := s.GetMode().Validate(); err != nil {
		return errors.WithStack(errors.Wrap(err, "spec.mode"))
	}
	if err := s.GetEnvironment().Validate(); err != nil {
		return errors.WithStack(errors.Wrap(err, "spec.environment"))
	}
	if err := s.GetStorageEngine().Validate(); err != nil {
		return errors.WithStack(errors.Wrap(err, "spec.storageEngine"))
	}
	if err := validatePullPolicy(s.GetImagePullPolicy()); err != nil {
		return errors.WithStack(errors.Wrap(err, "spec.imagePullPolicy"))
	}
	if s.GetImage() == "" {
		return errors.WithStack(errors.Wrapf(ValidationError, "spec.image must be set"))
	}
	if err := s.ExternalAccess.Validate(); err != nil {
		return errors.WithStack(errors.Wrap(err, "spec.externalAccess"))
	}
	if err := s.RocksDB.Validate(); err != nil {
		return errors.WithStack(errors.Wrap(err, "spec.rocksdb"))
	}
	if err := s.Authentication.Validate(false); err != nil {
		return errors.WithStack(errors.Wrap(err, "spec.auth"))
	}
	if err := s.TLS.Validate(); err != nil {
		return errors.WithStack(errors.Wrap(err, "spec.tls"))
	}
	if err := s.Sync.Validate(s.GetMode()); err != nil {
		return errors.WithStack(errors.Wrap(err, "spec.sync"))
	}
	if err := s.Single.Validate(ServerGroupSingle, s.GetMode().HasSingleServers(), s.GetMode(), s.GetEnvironment()); err != nil {
		return errors.WithStack(err)
	}
	if err := s.Agents.Validate(ServerGroupAgents, s.GetMode().HasAgents(), s.GetMode(), s.GetEnvironment()); err != nil {
		return errors.WithStack(err)
	}
	if err := s.DBServers.Validate(ServerGroupDBServers, s.GetMode().HasDBServers(), s.GetMode(), s.GetEnvironment()); err != nil {
		return errors.WithStack(err)
	}
	if err := s.Coordinators.Validate(ServerGroupCoordinators, s.GetMode().HasCoordinators(), s.GetMode(), s.GetEnvironment()); err != nil {
		return errors.WithStack(err)
	}
	if err := s.SyncMasters.Validate(ServerGroupSyncMasters, s.Sync.IsEnabled(), s.GetMode(), s.GetEnvironment()); err != nil {
		return errors.WithStack(err)
	}
	if err := s.SyncWorkers.Validate(ServerGroupSyncWorkers, s.Sync.IsEnabled(), s.GetMode(), s.GetEnvironment()); err != nil {
		return errors.WithStack(err)
	}
	if err := s.Metrics.Validate(); err != nil {
		return errors.WithStack(errors.Wrap(err, "spec.metrics"))
	}
	if err := s.Chaos.Validate(); err != nil {
		return errors.WithStack(errors.Wrap(err, "spec.chaos"))
	}
	if err := s.License.Validate(); err != nil {
		return errors.WithStack(errors.Wrap(err, "spec.licenseKey"))
	}
	if err := s.Bootstrap.Validate(); err != nil {
		return errors.WithStack(err)
	}
	return nil
}