mirror of
https://github.com/arangodb/kube-arangodb.git
synced 2024-12-14 11:57:37 +00:00
275 lines
8 KiB
Go
275 lines
8 KiB
Go
//
|
|
// DISCLAIMER
|
|
//
|
|
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
|
|
//
|
|
// Licensed 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.
|
|
//
|
|
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
|
//
|
|
|
|
package resources
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"math"
|
|
|
|
core "k8s.io/api/core/v1"
|
|
|
|
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
|
schedulerApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1beta1"
|
|
shared "github.com/arangodb/kube-arangodb/pkg/apis/shared"
|
|
"github.com/arangodb/kube-arangodb/pkg/deployment/features"
|
|
"github.com/arangodb/kube-arangodb/pkg/deployment/pod"
|
|
"github.com/arangodb/kube-arangodb/pkg/integrations/sidecar"
|
|
"github.com/arangodb/kube-arangodb/pkg/util/collection"
|
|
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
|
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
|
|
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil/interfaces"
|
|
kresources "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/resources"
|
|
)
|
|
|
|
var _ interfaces.PodCreator = &MemberGatewayPod{}
|
|
|
|
type MemberGatewayPod struct {
|
|
podName string
|
|
status api.MemberStatus
|
|
groupSpec api.ServerGroupSpec
|
|
spec api.DeploymentSpec
|
|
deploymentStatus api.DeploymentStatus
|
|
group api.ServerGroup
|
|
arangoMember api.ArangoMember
|
|
context Context
|
|
resources *Resources
|
|
imageInfo api.ImageInfo
|
|
cachedStatus interfaces.Inspector
|
|
}
|
|
|
|
func (m *MemberGatewayPod) GetName() string {
|
|
return m.resources.context.GetAPIObject().GetName()
|
|
}
|
|
|
|
func (m *MemberGatewayPod) GetRole() string {
|
|
return m.group.AsRole()
|
|
}
|
|
|
|
func (m *MemberGatewayPod) GetImagePullSecrets() []string {
|
|
return m.spec.ImagePullSecrets
|
|
}
|
|
|
|
func (m *MemberGatewayPod) GetPodAntiAffinity() *core.PodAntiAffinity {
|
|
a := &core.PodAntiAffinity{}
|
|
|
|
pod.AppendPodAntiAffinityDefault(m, a)
|
|
|
|
a = kresources.MergePodAntiAffinity(a, m.groupSpec.AntiAffinity)
|
|
|
|
return kresources.OptionalPodAntiAffinity(a)
|
|
}
|
|
|
|
func (m *MemberGatewayPod) AsInput() pod.Input {
|
|
return pod.Input{
|
|
ApiObject: m.context.GetAPIObject(),
|
|
Deployment: m.spec,
|
|
Status: m.deploymentStatus,
|
|
Group: m.group,
|
|
GroupSpec: m.groupSpec,
|
|
Version: m.imageInfo.ArangoDBVersion,
|
|
Enterprise: m.imageInfo.Enterprise,
|
|
Member: m.status,
|
|
ArangoMember: m.arangoMember,
|
|
}
|
|
}
|
|
|
|
func (m *MemberGatewayPod) GetPodAffinity() *core.PodAffinity {
|
|
a := &core.PodAffinity{}
|
|
|
|
pod.AppendAffinityWithRole(m, a, api.ServerGroupDBServers.AsRole())
|
|
|
|
a = kresources.MergePodAffinity(a, m.groupSpec.Affinity)
|
|
|
|
return kresources.OptionalPodAffinity(a)
|
|
}
|
|
|
|
func (m *MemberGatewayPod) GetNodeAffinity() *core.NodeAffinity {
|
|
a := &core.NodeAffinity{}
|
|
|
|
pod.AppendArchSelector(a, m.status.Architecture.Default(m.spec.Architecture.GetDefault()).AsNodeSelectorRequirement())
|
|
|
|
a = kresources.MergeNodeAffinity(a, m.groupSpec.NodeAffinity)
|
|
|
|
return kresources.OptionalNodeAffinity(a)
|
|
}
|
|
|
|
func (m *MemberGatewayPod) GetNodeSelector() map[string]string {
|
|
return m.groupSpec.GetNodeSelector()
|
|
}
|
|
|
|
func (m *MemberGatewayPod) GetServiceAccountName() string {
|
|
return m.groupSpec.GetServiceAccountName()
|
|
}
|
|
|
|
func (m *MemberGatewayPod) GetSidecars(pod *core.PodTemplateSpec) error {
|
|
// A sidecar provided by the user
|
|
sidecars := m.groupSpec.GetSidecars()
|
|
if len(sidecars) > 0 {
|
|
addLifecycleSidecar(m.groupSpec.SidecarCoreNames, sidecars)
|
|
pod.Spec.Containers = append(pod.Spec.Containers, sidecars...)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *MemberGatewayPod) GetVolumes() []core.Volume {
|
|
return createGatewayVolumes(m.AsInput()).Volumes()
|
|
}
|
|
|
|
func (m *MemberGatewayPod) IsDeploymentMode() bool {
|
|
return m.spec.IsDevelopment()
|
|
}
|
|
|
|
func (m *MemberGatewayPod) GetInitContainers(cachedStatus interfaces.Inspector) ([]core.Container, error) {
|
|
var initContainers []core.Container
|
|
if c := m.groupSpec.InitContainers.GetContainers(); len(c) > 0 {
|
|
initContainers = append(initContainers, c...)
|
|
}
|
|
|
|
res := kresources.ExtractPodInitContainerAcceptedResourceRequirement(m.GetContainerCreator().GetResourceRequirements())
|
|
|
|
initContainers = applyInitContainersResourceResources(initContainers, res)
|
|
initContainers = upscaleInitContainersResourceResources(initContainers, res)
|
|
|
|
return initContainers, nil
|
|
}
|
|
|
|
func (m *MemberGatewayPod) GetFinalizers() []string {
|
|
return nil
|
|
}
|
|
|
|
func (m *MemberGatewayPod) GetTolerations() []core.Toleration {
|
|
return m.resources.CreatePodTolerations(m.group, m.groupSpec)
|
|
}
|
|
|
|
func (m *MemberGatewayPod) GetContainerCreator() interfaces.ContainerCreator {
|
|
return &ArangoGatewayContainer{
|
|
member: m,
|
|
spec: m.spec,
|
|
group: m.group,
|
|
resources: m.resources,
|
|
imageInfo: m.imageInfo,
|
|
groupSpec: m.groupSpec,
|
|
arangoMember: m.arangoMember,
|
|
cachedStatus: m.cachedStatus,
|
|
input: m.AsInput(),
|
|
status: m.status,
|
|
}
|
|
}
|
|
|
|
func (m *MemberGatewayPod) GetRestartPolicy() core.RestartPolicy {
|
|
if features.RestartPolicyAlways().Enabled() {
|
|
return core.RestartPolicyAlways
|
|
}
|
|
return core.RestartPolicyNever
|
|
}
|
|
|
|
func (m *MemberGatewayPod) Init(ctx context.Context, cachedStatus interfaces.Inspector, pod *core.PodTemplateSpec) error {
|
|
terminationGracePeriodSeconds := int64(math.Ceil(m.groupSpec.GetTerminationGracePeriod(m.group).Seconds()))
|
|
pod.Spec.TerminationGracePeriodSeconds = &terminationGracePeriodSeconds
|
|
pod.Spec.PriorityClassName = m.groupSpec.PriorityClassName
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *MemberGatewayPod) Validate(cachedStatus interfaces.Inspector) error {
|
|
i := m.AsInput()
|
|
|
|
if err := pod.SNI().Verify(i, cachedStatus); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := validateSidecars(m.groupSpec.SidecarCoreNames, m.groupSpec.GetSidecars()); err != nil {
|
|
return err
|
|
}
|
|
|
|
if c, err := cachedStatus.ArangoProfile().V1Beta1(); err != nil {
|
|
return err
|
|
} else {
|
|
if _, ok := c.GetSimple(fmt.Sprintf("%s-int", m.context.GetName())); !ok {
|
|
return errors.Errorf("Unable to find deployment integration")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *MemberGatewayPod) ApplyPodSpec(spec *core.PodSpec) error {
|
|
if s := m.groupSpec.SchedulerName; s != nil {
|
|
spec.SchedulerName = *s
|
|
}
|
|
|
|
m.groupSpec.PodModes.Apply(spec)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *MemberGatewayPod) Annotations() map[string]string {
|
|
return collection.MergeAnnotations(m.spec.Annotations, m.groupSpec.Annotations)
|
|
}
|
|
|
|
func (m *MemberGatewayPod) Labels() map[string]string {
|
|
l := collection.ReservedLabels().Filter(collection.MergeAnnotations(m.spec.Labels, m.groupSpec.Labels))
|
|
|
|
if m.status.Topology != nil && m.deploymentStatus.Topology.Enabled() && m.deploymentStatus.Topology.ID == m.status.Topology.ID {
|
|
if l == nil {
|
|
l = map[string]string{}
|
|
}
|
|
|
|
l[k8sutil.LabelKeyArangoZone] = fmt.Sprintf("%d", m.status.Topology.Zone)
|
|
l[k8sutil.LabelKeyArangoTopology] = string(m.status.Topology.ID)
|
|
}
|
|
|
|
return l
|
|
}
|
|
|
|
func (m *MemberGatewayPod) Profiles() (schedulerApi.ProfileTemplates, error) {
|
|
c, err := m.cachedStatus.ArangoProfile().V1Beta1()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
integration, ok := c.GetSimple(fmt.Sprintf("%s-int", m.context.GetName()))
|
|
if !ok {
|
|
return nil, errors.Errorf("Unable to find deployment integration")
|
|
}
|
|
|
|
if integration.Status.Accepted == nil {
|
|
return nil, errors.Errorf("Unable to find accepted integration integration")
|
|
}
|
|
|
|
integrations, err := sidecar.NewIntegrationEnablement(
|
|
sidecar.IntegrationEnvoyV3{
|
|
Spec: m.spec,
|
|
}, sidecar.IntegrationAuthenticationV1{
|
|
DeploymentName: m.context.GetName(),
|
|
Spec: m.spec,
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
shutdownAnnotation := sidecar.NewShutdownAnnotations([]string{shared.ServerContainerName})
|
|
|
|
return []*schedulerApi.ProfileTemplate{integration.Status.Accepted.Template, integrations, shutdownAnnotation}, nil
|
|
}
|