Skip to content

Commit

Permalink
[Feature] Fix numactl options (#1432)
Browse files Browse the repository at this point in the history
  • Loading branch information
ajanikow authored Oct 11, 2023
1 parent ff34073 commit 5e5e43d
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 22 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- (Improvement) Allow tcp:// and ssl:// protocols in endpoints for members
- (Maintenance) Reorganize package imports / move common code to separate repos
- (Maintenance) Remove support for RELATED_IMAGE_UBI, RELATED_IMAGE_DATABASE and RELATED_IMAGE_METRICSEXPORTER env vars
- (Bugfix) Fix numactl options

## [1.2.33](https://github.com/arangodb/kube-arangodb/tree/1.2.33) (2023-09-27)
- (Maintenance) Bump golang.org/x/net to v0.13.0
Expand Down
184 changes: 184 additions & 0 deletions pkg/deployment/deployment_core_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,190 @@ func TestEnsurePod_ArangoDB_Core(t *testing.T) {
},
},
},
{
Name: "Agent Pod with numactl",
ArangoDeployment: &api.ArangoDeployment{
Spec: api.DeploymentSpec{
Image: util.NewType[string](testImage),
Authentication: noAuthentication,
TLS: noTLS,
ImagePullPolicy: util.NewType[core.PullPolicy](core.PullAlways),

Agents: api.ServerGroupSpec{
Numactl: &api.ServerGroupSpecNumactl{
Enabled: util.NewType(true),
},
},
},
},
Helper: func(t *testing.T, deployment *Deployment, testCase *testCaseStruct) {
deployment.currentObjectStatus = &api.DeploymentStatus{
Members: api.DeploymentStatusMembers{
Agents: api.MemberStatusList{
firstAgentStatus,
},
},
Images: createTestImages(false),
}
testCase.createTestPodData(deployment, api.ServerGroupAgents, firstAgentStatus)
},
ExpectedEvent: "member agent is created",
ExpectedPod: core.Pod{
Spec: core.PodSpec{
Volumes: []core.Volume{
k8sutil.CreateVolumeEmptyDir(shared.ArangodVolumeName),
},
Containers: []core.Container{
{
Name: shared.ServerContainerName,
Image: testImage,
Command: util.List[string]{api.ServerGroupSpecNumactlPathDefault}.
Append(createTestCommandForAgent(firstAgentStatus.ID, false, false, false)...).
List(),
Ports: createTestPorts(api.ServerGroupAgents),
VolumeMounts: []core.VolumeMount{
k8sutil.ArangodVolumeMount(),
},
Resources: emptyResources,
LivenessProbe: createTestLivenessProbe(httpProbe, false, "", shared.ServerPortName),
ImagePullPolicy: core.PullAlways,
SecurityContext: securityContext.NewSecurityContext(),
},
},
RestartPolicy: core.RestartPolicyNever,
TerminationGracePeriodSeconds: &defaultAgentTerminationTimeout,
Hostname: testDeploymentName + "-" + api.ServerGroupAgentsString + "-" + firstAgentStatus.ID,
Subdomain: testDeploymentName + "-int",
Affinity: k8sutil.CreateAffinity(testDeploymentName, api.ServerGroupAgentsString,
false, ""),
},
},
},
{
Name: "Agent Pod with numactl with opts and override",
ArangoDeployment: &api.ArangoDeployment{
Spec: api.DeploymentSpec{
Image: util.NewType[string](testImage),
Authentication: noAuthentication,
TLS: noTLS,
ImagePullPolicy: util.NewType[core.PullPolicy](core.PullAlways),

Agents: api.ServerGroupSpec{
Numactl: &api.ServerGroupSpecNumactl{
Enabled: util.NewType(true),
Args: []string{
"--example=all",
},
Path: util.NewType("numactl-random-version"),
},
},
},
},
Helper: func(t *testing.T, deployment *Deployment, testCase *testCaseStruct) {
deployment.currentObjectStatus = &api.DeploymentStatus{
Members: api.DeploymentStatusMembers{
Agents: api.MemberStatusList{
firstAgentStatus,
},
},
Images: createTestImages(false),
}
testCase.createTestPodData(deployment, api.ServerGroupAgents, firstAgentStatus)
},
ExpectedEvent: "member agent is created",
ExpectedPod: core.Pod{
Spec: core.PodSpec{
Volumes: []core.Volume{
k8sutil.CreateVolumeEmptyDir(shared.ArangodVolumeName),
},
Containers: []core.Container{
{
Name: shared.ServerContainerName,
Image: testImage,
Command: util.List[string]{"numactl-random-version", "--example=all"}.
Append(createTestCommandForAgent(firstAgentStatus.ID, false, false, false)...).
List(),
Ports: createTestPorts(api.ServerGroupAgents),
VolumeMounts: []core.VolumeMount{
k8sutil.ArangodVolumeMount(),
},
Resources: emptyResources,
LivenessProbe: createTestLivenessProbe(httpProbe, false, "", shared.ServerPortName),
ImagePullPolicy: core.PullAlways,
SecurityContext: securityContext.NewSecurityContext(),
},
},
RestartPolicy: core.RestartPolicyNever,
TerminationGracePeriodSeconds: &defaultAgentTerminationTimeout,
Hostname: testDeploymentName + "-" + api.ServerGroupAgentsString + "-" + firstAgentStatus.ID,
Subdomain: testDeploymentName + "-int",
Affinity: k8sutil.CreateAffinity(testDeploymentName, api.ServerGroupAgentsString,
false, ""),
},
},
},
{
Name: "Agent Pod with numactl with opts",
ArangoDeployment: &api.ArangoDeployment{
Spec: api.DeploymentSpec{
Image: util.NewType[string](testImage),
Authentication: noAuthentication,
TLS: noTLS,
ImagePullPolicy: util.NewType[core.PullPolicy](core.PullAlways),

Agents: api.ServerGroupSpec{
Numactl: &api.ServerGroupSpecNumactl{
Enabled: util.NewType(true),
Args: []string{
"--example=all",
},
},
},
},
},
Helper: func(t *testing.T, deployment *Deployment, testCase *testCaseStruct) {
deployment.currentObjectStatus = &api.DeploymentStatus{
Members: api.DeploymentStatusMembers{
Agents: api.MemberStatusList{
firstAgentStatus,
},
},
Images: createTestImages(false),
}
testCase.createTestPodData(deployment, api.ServerGroupAgents, firstAgentStatus)
},
ExpectedEvent: "member agent is created",
ExpectedPod: core.Pod{
Spec: core.PodSpec{
Volumes: []core.Volume{
k8sutil.CreateVolumeEmptyDir(shared.ArangodVolumeName),
},
Containers: []core.Container{
{
Name: shared.ServerContainerName,
Image: testImage,
Command: util.List[string]{api.ServerGroupSpecNumactlPathDefault, "--example=all"}.
Append(createTestCommandForAgent(firstAgentStatus.ID, false, false, false)...).
List(),
Ports: createTestPorts(api.ServerGroupAgents),
VolumeMounts: []core.VolumeMount{
k8sutil.ArangodVolumeMount(),
},
Resources: emptyResources,
LivenessProbe: createTestLivenessProbe(httpProbe, false, "", shared.ServerPortName),
ImagePullPolicy: core.PullAlways,
SecurityContext: securityContext.NewSecurityContext(),
},
},
RestartPolicy: core.RestartPolicyNever,
TerminationGracePeriodSeconds: &defaultAgentTerminationTimeout,
Hostname: testDeploymentName + "-" + api.ServerGroupAgentsString + "-" + firstAgentStatus.ID,
Subdomain: testDeploymentName + "-int",
Affinity: k8sutil.CreateAffinity(testDeploymentName, api.ServerGroupAgentsString,
false, ""),
},
},
},
{
Name: "Agent Pod with image pull policy",
ArangoDeployment: &api.ArangoDeployment{
Expand Down
10 changes: 5 additions & 5 deletions pkg/deployment/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -393,8 +393,8 @@ func (i *ImageUpdatePod) ApplyPodSpec(p *core.PodSpec) error {
return nil
}

func (a *ContainerIdentity) GetArgs() ([]string, error) {
return nil, nil
func (a *ContainerIdentity) GetCommand() ([]string, error) {
return []string{a.GetExecutor()}, nil
}

// GetEnvs returns environment variables for identity containers.
Expand Down Expand Up @@ -449,8 +449,8 @@ func (a *ContainerIdentity) GetVolumeMounts() []core.VolumeMount {
return nil
}

// GetArgs returns the list of arguments for the ArangoD container identification.
func (a *ArangoDIdentity) GetArgs() ([]string, error) {
// GetCommand returns the command for the ArangoD container identification.
func (a *ArangoDIdentity) GetCommand() ([]string, error) {
options := k8sutil.CreateOptionPairs(64)
options.Add("--server.authentication", "false")
options.Addf("--server.endpoint", "tcp://%s:%d", a.ipAddress, shared.ArangoPort)
Expand All @@ -460,7 +460,7 @@ func (a *ArangoDIdentity) GetArgs() ([]string, error) {
// Security
options.Merge(pod.Security().Args(a.input))

return options.Copy().Sort().AsArgs(), nil
return options.Copy().Sort().AsArgsWithCommand(a.GetExecutor()), nil
}

// GetEnvs returns environment variables for Arango identity containers.
Expand Down
21 changes: 11 additions & 10 deletions pkg/deployment/resources/pod_creator_arangod.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,22 +121,23 @@ func (a *ArangoDContainer) GetPorts() []core.ContainerPort {
return ports
}

func (a *ArangoDContainer) GetArgs() ([]string, error) {
func (a *ArangoDContainer) GetCommand() ([]string, error) {
cmd := make([]string, 0, 128)

if args := createArangodNumactl(a.groupSpec); len(args) > 0 {
cmd = append(cmd, args...)
}

cmd = append(cmd, a.GetExecutor())

args, err := createArangodArgs(a.cachedStatus, a.input)
if err != nil {
return nil, err
}

if nmargs := createArangodNumactl(a.groupSpec); len(nmargs) > 0 {
vs := make([]string, len(args)+len(nmargs))

copy(vs, nmargs)
copy(vs[len(nmargs):], args)

return vs, nil
}
cmd = append(cmd, args...)

return args, nil
return cmd, nil
}

func (a *ArangoDContainer) GetName() string {
Expand Down
7 changes: 5 additions & 2 deletions pkg/deployment/resources/pod_creator_sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,11 @@ type MemberSyncPod struct {
cachedStatus interfaces.Inspector
}

func (a *ArangoSyncContainer) GetArgs() ([]string, error) {
return createArangoSyncArgs(a.apiObject, a.spec, a.group, a.groupSpec, a.memberStatus), nil
func (a *ArangoSyncContainer) GetCommand() ([]string, error) {
cmd := make([]string, 0, 128)
cmd = append(cmd, a.GetExecutor())
cmd = append(cmd, createArangoSyncArgs(a.apiObject, a.spec, a.group, a.groupSpec, a.memberStatus)...)
return cmd, nil
}

func (a *ArangoSyncContainer) GetName() string {
Expand Down
4 changes: 2 additions & 2 deletions pkg/util/k8sutil/interfaces/pod_creator.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//
// DISCLAIMER
//
// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
// Copyright 2016-2023 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.
Expand Down Expand Up @@ -65,7 +65,7 @@ type PodCreator interface {
}

type ContainerCreator interface {
GetArgs() ([]string, error)
GetCommand() ([]string, error)
GetName() string
GetExecutor() string
GetProbes() (*core.Probe, *core.Probe, *core.Probe, error)
Expand Down
14 changes: 13 additions & 1 deletion pkg/util/k8sutil/pair.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//
// DISCLAIMER
//
// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
// Copyright 2016-2023 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.
Expand Down Expand Up @@ -126,6 +126,18 @@ func (o OptionPairs) Sort() OptionPairs {
return o
}

func (o OptionPairs) AsArgsWithCommand(command string) []string {
s := make([]string, len(o)+1)

s[0] = command

for id, pair := range o {
s[id+1] = pair.String()
}

return s
}

func (o OptionPairs) AsArgs() []string {
s := make([]string, len(o))

Expand Down
4 changes: 2 additions & 2 deletions pkg/util/k8sutil/pods.go
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ func NewContainer(containerCreator interfaces.ContainerCreator) (core.Container,
return core.Container{}, err
}

args, err := containerCreator.GetArgs()
cmd, err := containerCreator.GetCommand()
if err != nil {
return core.Container{}, err
}
Expand All @@ -554,7 +554,7 @@ func NewContainer(containerCreator interfaces.ContainerCreator) (core.Container,
return core.Container{
Name: containerCreator.GetName(),
Image: containerCreator.GetImage(),
Command: append([]string{containerCreator.GetExecutor()}, args...),
Command: cmd,
Ports: containerCreator.GetPorts(),
Env: env,
EnvFrom: envFrom,
Expand Down
8 changes: 8 additions & 0 deletions pkg/util/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ func (l List[T]) Count(fn func(T) bool) int {
return len(l.Filter(fn))
}

func (l List[T]) Append(items ...T) List[T] {
return append(l, items...)
}

func (l List[T]) List() []T {
return l
}

func (l List[T]) Sort(fn func(T, T) bool) List[T] {
clone := l
sort.Slice(clone, func(i, j int) bool {
Expand Down

0 comments on commit 5e5e43d

Please sign in to comment.