Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Add new admin commands to fetch agency dump and agency state
- Add Graceful shutdown as finalizer (supports kubectl delete)
- Add Watch to Lifecycle command
- Add Topology Discovery

## [1.2.4](https://github.com/arangodb/kube-arangodb/tree/1.2.4) (2021-10-22)
- Replace `beta.kubernetes.io/arch` Pod label with `kubernetes.io/arch` using Silent Rotation
Expand Down
1 change: 1 addition & 0 deletions pkg/deployment/reconcile/plan_builder_high.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ func createHighPlan(ctx context.Context, log zerolog.Logger, apiObject k8sutil.A
ApplyIfEmpty(createCleanOutPlan).
ApplyIfEmpty(updateMemberUpdateConditionsPlan).
ApplyIfEmpty(updateMemberRotationConditionsPlan).
ApplyIfEmpty(createTopologyMemberUpdatePlan).
ApplyIfEmpty(createTopologyMemberConditionPlan).
Plan(), true
}
Expand Down
6 changes: 6 additions & 0 deletions pkg/deployment/reconcile/plan_builder_topology.community.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ func createTopologyEnablementPlan(ctx context.Context,
cachedStatus inspectorInterface.Inspector, context PlanBuilderContext) api.Plan {
return nil
}
func createTopologyMemberUpdatePlan(ctx context.Context,
log zerolog.Logger, apiObject k8sutil.APIObject,
spec api.DeploymentSpec, status api.DeploymentStatus,
cachedStatus inspectorInterface.Inspector, context PlanBuilderContext) api.Plan {
return nil
}

func createTopologyMemberConditionPlan(ctx context.Context,
log zerolog.Logger, apiObject k8sutil.APIObject,
Expand Down
48 changes: 41 additions & 7 deletions pkg/deployment/rotation/arangod_containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ package rotation
import (
"strings"

"github.com/arangodb/kube-arangodb/pkg/deployment/topology"

"k8s.io/apimachinery/pkg/api/equality"

api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
Expand All @@ -50,15 +52,26 @@ func containersCompare(_ api.DeploymentSpec, _ api.ServerGroup, spec, status *co
for id := range a {
if ac, bc := &a[id], &b[id]; ac.Name == bc.Name {
if ac.Name == api.ServerGroupReservedContainerNameServer {
if !isOnlyLogLevelChanged(ac.Command, bc.Command) {
continue
}
if isOnlyLogLevelChanged(ac.Command, bc.Command) {
plan = append(plan, builder.NewAction(api.ActionTypeRuntimeContainerArgsLogLevelUpdate).
AddParam(ContainerName, ac.Name))

plan = append(plan, builder.NewAction(api.ActionTypeRuntimeContainerArgsLogLevelUpdate).
AddParam(ContainerName, ac.Name))
bc.Command = ac.Command
mode = mode.And(InPlaceRotation)
}

bc.Command = ac.Command
mode = mode.And(InPlaceRotation)
if !equality.Semantic.DeepEqual(ac.Env, bc.Env) {
if areEnvsEqual(ac.Env, bc.Env, func(a, b map[string]core.EnvVar) (map[string]core.EnvVar, map[string]core.EnvVar) {
if _, ok := a[topology.ArangoDBZone]; !ok {
delete(b, topology.ArangoDBZone)
}

return a, b
}) {
bc.Env = ac.Env
mode = mode.And(SilentRotation)
}
}
} else {
if ac.Image != bc.Image {
// Image changed
Expand Down Expand Up @@ -162,3 +175,24 @@ func internalContainerLifecycleCompare(spec, status *core.Container) Mode {

return SkippedRotation
}

func areEnvsEqual(a, b []core.EnvVar, rules ...func(a, b map[string]core.EnvVar) (map[string]core.EnvVar, map[string]core.EnvVar)) bool {
am := getEnvs(a)
bm := getEnvs(b)

for _, r := range rules {
am, bm = r(am, bm)
}

return equality.Semantic.DeepEqual(am, bm)
}

func getEnvs(e []core.EnvVar) map[string]core.EnvVar {
m := map[string]core.EnvVar{}

for _, q := range e {
m[q.Name] = q
}

return m
}
149 changes: 149 additions & 0 deletions pkg/deployment/rotation/arangod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ package rotation
import (
"testing"

"github.com/arangodb/kube-arangodb/pkg/deployment/topology"

core "k8s.io/api/core/v1"
)

Expand Down Expand Up @@ -177,3 +179,150 @@ func Test_ArangoD_Affinity(t *testing.T) {

runTestCases(t)(testCases...)
}

func Test_ArangoD_Labels(t *testing.T) {
testCases := []TestCase{
{
name: "Add label",

spec: buildPodSpec(func(pod *core.PodTemplateSpec) {
pod.Labels = map[string]string{}
}),

status: buildPodSpec(func(pod *core.PodTemplateSpec) {
pod.Labels = map[string]string{
"A": "B",
}
}),

expectedMode: SkippedRotation,
},
{
name: "Remove label",

spec: buildPodSpec(func(pod *core.PodTemplateSpec) {
pod.Labels = map[string]string{
"A": "B",
}
}),

status: buildPodSpec(func(pod *core.PodTemplateSpec) {
pod.Labels = map[string]string{}
}),

expectedMode: SkippedRotation,
},
{
name: "Change label",

spec: buildPodSpec(func(pod *core.PodTemplateSpec) {
pod.Labels = map[string]string{
"A": "A",
}
}),

status: buildPodSpec(func(pod *core.PodTemplateSpec) {
pod.Labels = map[string]string{
"A": "B",
}
}),

expectedMode: SkippedRotation,
},
}

runTestCases(t)(testCases...)
}

func Test_ArangoD_Envs_Zone(t *testing.T) {
testCases := []TestCase{
{
name: "Add Zone env",

spec: buildPodSpec(addContainer("server", func(c *core.Container) {
c.Env = []core.EnvVar{}
})),

status: buildPodSpec(addContainer("server", func(c *core.Container) {
c.Env = []core.EnvVar{
{
Name: topology.ArangoDBZone,
Value: "A",
},
}
})),

expectedMode: SilentRotation,
},
{
name: "Remove Zone env",

spec: buildPodSpec(addContainer("server", func(c *core.Container) {
c.Env = []core.EnvVar{
{
Name: topology.ArangoDBZone,
Value: "A",
},
}
})),

status: buildPodSpec(addContainer("server", func(c *core.Container) {
c.Env = []core.EnvVar{}
})),

expectedMode: GracefulRotation,
},
{
name: "Update Zone env",

spec: buildPodSpec(addContainer("server", func(c *core.Container) {
c.Env = []core.EnvVar{
{
Name: topology.ArangoDBZone,
Value: "A",
},
}
})),

status: buildPodSpec(addContainer("server", func(c *core.Container) {
c.Env = []core.EnvVar{
{
Name: topology.ArangoDBZone,
Value: "B",
},
}
})),

expectedMode: GracefulRotation,
},
{
name: "Update other env",

spec: buildPodSpec(addContainer("server", func(c *core.Container) {
c.Env = []core.EnvVar{
{
Name: "Q",
Value: "A",
},
{
Name: topology.ArangoDBZone,
Value: "A",
},
}
})),

status: buildPodSpec(addContainer("server", func(c *core.Container) {
c.Env = []core.EnvVar{
{
Name: topology.ArangoDBZone,
Value: "A",
},
}
})),

expectedMode: GracefulRotation,
},
}

runTestCases(t)(testCases...)
}
9 changes: 7 additions & 2 deletions pkg/deployment/rotation/compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
package rotation

import (
"encoding/json"

api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
"github.com/arangodb/kube-arangodb/pkg/deployment/resources"
"github.com/rs/zerolog"
Expand Down Expand Up @@ -88,10 +90,13 @@ func compare(log zerolog.Logger, deploymentSpec api.DeploymentSpec, member api.M
}

if spec.RotationNeeded(newStatus) {
specData, _ := json.Marshal(spec)
statusData, _ := json.Marshal(newStatus)

log.Info().Str("before", spec.PodSpecChecksum).
Str("id", member.ID).
Interface("spec", spec).
Interface("status", newStatus).
Str("spec", string(specData)).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not Interface? error must be checked in this case.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried to do this, but in logs it did not look soo nice (and you couldn't compare it, for example via json compare)

Str("status", string(statusData)).
Msg("Pod needs rotation - templates does not match")

return GracefulRotation, nil, nil
Expand Down