Skip to content

Commit 5f786f6

Browse files
authored
Merge pull request #277 from arangodb/bug-fix/break-pks-loop
Break PKS Loop
2 parents 0cc576e + d5a54a2 commit 5f786f6

11 files changed

+226
-3
lines changed

pkg/apis/deployment/v1alpha/conditions.go

+31
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
package v1alpha
2424

2525
import (
26+
"github.com/arangodb/kube-arangodb/pkg/util"
2627
"k8s.io/api/core/v1"
2728
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2829
)
@@ -76,6 +77,36 @@ type Condition struct {
7677
// Each type is allowed only once.
7778
type ConditionList []Condition
7879

80+
// Equal checks for equality
81+
func (list ConditionList) Equal(other ConditionList) bool {
82+
if len(list) != len(other) {
83+
return false
84+
}
85+
86+
for i := 0; i < len(list); i++ {
87+
c, found := other.Get(list[i].Type)
88+
if !found {
89+
return false
90+
}
91+
92+
if !list[i].Equal(c) {
93+
return false
94+
}
95+
}
96+
97+
return true
98+
}
99+
100+
// Equal checks for equality
101+
func (c Condition) Equal(other Condition) bool {
102+
return c.Type == other.Type &&
103+
c.Status == other.Status &&
104+
util.TimeCompareEqual(c.LastUpdateTime, other.LastUpdateTime) &&
105+
util.TimeCompareEqual(c.LastTransitionTime, other.LastTransitionTime) &&
106+
c.Reason == other.Reason &&
107+
c.Message == other.Message
108+
}
109+
79110
// IsTrue return true when a condition with given type exists and its status is `True`.
80111
func (list ConditionList) IsTrue(conditionType ConditionType) bool {
81112
c, found := list.Get(conditionType)

pkg/apis/deployment/v1alpha/deployment_spec.go

+7
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
package v1alpha
2424

2525
import (
26+
"reflect"
27+
2628
"github.com/arangodb/kube-arangodb/pkg/util"
2729
"github.com/pkg/errors"
2830
"k8s.io/api/core/v1"
@@ -69,6 +71,11 @@ type DeploymentSpec struct {
6971
Chaos ChaosSpec `json:"chaos"`
7072
}
7173

74+
// Equal compares two DeploymentSpec
75+
func (s *DeploymentSpec) Equal(other *DeploymentSpec) bool {
76+
return reflect.DeepEqual(s, other)
77+
}
78+
7279
// GetMode returns the value of mode.
7380
func (s DeploymentSpec) GetMode() DeploymentMode {
7481
return ModeOrDefault(s.Mode)

pkg/apis/deployment/v1alpha/deployment_status.go

+15
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,18 @@ type DeploymentStatus struct {
5757
// detect changes in secret values.
5858
SecretHashes *SecretHashes `json:"secret-hashes,omitempty"`
5959
}
60+
61+
// Equal checks for equality
62+
func (ds *DeploymentStatus) Equal(other DeploymentStatus) bool {
63+
return ds.Phase == other.Phase &&
64+
ds.Reason == other.Reason &&
65+
ds.ServiceName == other.ServiceName &&
66+
ds.SyncServiceName == other.SyncServiceName &&
67+
ds.Images.Equal(other.Images) &&
68+
ds.CurrentImage.Equal(other.CurrentImage) &&
69+
ds.Members.Equal(other.Members) &&
70+
ds.Conditions.Equal(other.Conditions) &&
71+
ds.Plan.Equal(other.Plan) &&
72+
ds.AcceptedSpec.Equal(other.AcceptedSpec) &&
73+
ds.SecretHashes.Equal(other.SecretHashes)
74+
}

pkg/apis/deployment/v1alpha/deployment_status_members.go

+10
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ type DeploymentStatusMembers struct {
3636
SyncWorkers MemberStatusList `json:"syncworkers,omitempty"`
3737
}
3838

39+
// Equal checks for equality
40+
func (ds DeploymentStatusMembers) Equal(other DeploymentStatusMembers) bool {
41+
return ds.Single.Equal(other.Single) &&
42+
ds.Agents.Equal(other.Agents) &&
43+
ds.DBServers.Equal(other.DBServers) &&
44+
ds.Coordinators.Equal(other.Coordinators) &&
45+
ds.SyncMasters.Equal(other.SyncMasters) &&
46+
ds.SyncWorkers.Equal(other.SyncWorkers)
47+
}
48+
3949
// ContainsID returns true if the given set of members contains a member with given ID.
4050
func (ds DeploymentStatusMembers) ContainsID(id string) bool {
4151
return ds.Single.ContainsID(id) ||

pkg/apis/deployment/v1alpha/image_info.go

+35
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,38 @@ func (l *ImageInfoList) AddOrUpdate(info ImageInfo) {
7171
// No existing entry found, add it
7272
*l = append(*l, info)
7373
}
74+
75+
// Equal compares to ImageInfo
76+
func (i *ImageInfo) Equal(other *ImageInfo) bool {
77+
if i == nil || other == nil {
78+
return false
79+
} else if i == other {
80+
return true
81+
}
82+
83+
return i.ArangoDBVersion == other.ArangoDBVersion &&
84+
i.Enterprise == other.Enterprise &&
85+
i.Image == other.Image &&
86+
i.ImageID == other.ImageID
87+
}
88+
89+
// Equal compares to ImageInfoList
90+
func (l ImageInfoList) Equal(other ImageInfoList) bool {
91+
if len(l) != len(other) {
92+
return false
93+
}
94+
95+
for i := 0; i < len(l); i++ {
96+
ii, found := l.GetByImageID(l[i].ImageID)
97+
98+
if !found {
99+
return false
100+
}
101+
102+
if !l[i].Equal(&ii) {
103+
return false
104+
}
105+
}
106+
107+
return true
108+
}

pkg/apis/deployment/v1alpha/member_status.go

+13
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ package v1alpha
2525
import (
2626
"time"
2727

28+
"github.com/arangodb/kube-arangodb/pkg/util"
2829
"k8s.io/api/core/v1"
2930
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3031
)
@@ -54,6 +55,18 @@ type MemberStatus struct {
5455
CleanoutJobID string `json:"cleanout-job-id,omitempty"`
5556
}
5657

58+
// Equal checks for equality
59+
func (s MemberStatus) Equal(other MemberStatus) bool {
60+
return s.ID == other.ID &&
61+
s.Phase == other.Phase &&
62+
util.TimeCompareEqual(s.CreatedAt, other.CreatedAt) &&
63+
s.PersistentVolumeClaimName == other.PersistentVolumeClaimName &&
64+
s.PodName == other.PodName &&
65+
s.Conditions.Equal(other.Conditions) &&
66+
s.IsInitialized == other.IsInitialized &&
67+
s.CleanoutJobID == other.CleanoutJobID
68+
}
69+
5770
// Age returns the duration since the creation timestamp of this member.
5871
func (s MemberStatus) Age() time.Duration {
5972
return time.Since(s.CreatedAt.Time)

pkg/apis/deployment/v1alpha/member_status_list.go

+20
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,26 @@ import (
3232
// MemberStatusList is a list of MemberStatus entries
3333
type MemberStatusList []MemberStatus
3434

35+
// Equal checks for equality
36+
func (l MemberStatusList) Equal(other MemberStatusList) bool {
37+
if len(l) != len(other) {
38+
return false
39+
}
40+
41+
for i := 0; i < len(l); i++ {
42+
o, found := l.ElementByID(l[i].ID)
43+
if !found {
44+
return false
45+
}
46+
47+
if !l[i].Equal(o) {
48+
return false
49+
}
50+
}
51+
52+
return true
53+
}
54+
3555
// ContainsID returns true if the given list contains a member with given ID.
3656
func (l MemberStatusList) ContainsID(id string) bool {
3757
for _, x := range l {

pkg/apis/deployment/v1alpha/plan.go

+29
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
package v1alpha
2424

2525
import (
26+
"github.com/arangodb/kube-arangodb/pkg/util"
2627
"github.com/dchest/uniuri"
2728
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2829
)
@@ -79,6 +80,18 @@ type Action struct {
7980
Image string `json:"image,omitempty"`
8081
}
8182

83+
// Equal compares two Actions
84+
func (a Action) Equal(other Action) bool {
85+
return a.ID == other.ID &&
86+
a.Type == other.Type &&
87+
a.MemberID == other.MemberID &&
88+
a.Group == other.Group &&
89+
util.TimeCompareEqual(a.CreationTime, other.CreationTime) &&
90+
util.TimeCompareEqualPointer(a.StartTime, other.StartTime) &&
91+
a.Reason == other.Reason &&
92+
a.Image == other.Image
93+
}
94+
8295
// NewAction instantiates a new Action.
8396
func NewAction(actionType ActionType, group ServerGroup, memberID string, reason ...string) Action {
8497
a := Action{
@@ -105,3 +118,19 @@ func (a Action) SetImage(image string) Action {
105118
// Only 1 action is in progress at a time. The operator will wait for that
106119
// action to be completely and then remove the action.
107120
type Plan []Action
121+
122+
// Equal compares two Plan
123+
func (p Plan) Equal(other Plan) bool {
124+
// For plan the order is relevant!
125+
if len(p) != len(other) {
126+
return false
127+
}
128+
129+
for i := 0; i < len(p); i++ {
130+
if !p[i].Equal(other[i]) {
131+
return false
132+
}
133+
}
134+
135+
return true
136+
}

pkg/apis/deployment/v1alpha/secret_hashes.go

+14
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,17 @@ type SecretHashes struct {
3535
// SyncTLSCA contains the hash of the sync.tls.caSecretName secret
3636
SyncTLSCA string `json:"sync-tls-ca,omitempty"`
3737
}
38+
39+
// Equal compares two SecretHashes
40+
func (sh *SecretHashes) Equal(other *SecretHashes) bool {
41+
if sh == nil || other == nil {
42+
return false
43+
} else if sh == other {
44+
return true
45+
}
46+
47+
return sh.AuthJWT == other.AuthJWT &&
48+
sh.RocksDBEncryptionKey == other.RocksDBEncryptionKey &&
49+
sh.TLSCA == other.TLSCA &&
50+
sh.SyncTLSCA == other.SyncTLSCA
51+
}

pkg/deployment/deployment.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ package deployment
2424

2525
import (
2626
"fmt"
27-
"reflect"
2827
"sync"
2928
"sync/atomic"
3029
"time"
@@ -344,9 +343,8 @@ func (d *Deployment) CreateEvent(evt *k8sutil.Event) {
344343

345344
// Update the status of the API object from the internal status
346345
func (d *Deployment) updateCRStatus(force ...bool) error {
347-
// TODO Remove force....
348346
if len(force) == 0 || !force[0] {
349-
if reflect.DeepEqual(d.apiObject.Status, d.status) {
347+
if d.apiObject.Status.Equal(d.status.last) {
350348
// Nothing has changed
351349
return nil
352350
}
@@ -390,6 +388,12 @@ func (d *Deployment) updateCRStatus(force ...bool) error {
390388
// to the given object, while preserving the status.
391389
// On success, d.apiObject is updated.
392390
func (d *Deployment) updateCRSpec(newSpec api.DeploymentSpec) error {
391+
392+
if d.apiObject.Spec.Equal(&newSpec) {
393+
// Nothing to update
394+
return nil
395+
}
396+
393397
// Send update to API server
394398
update := d.apiObject.DeepCopy()
395399
attempt := 0

pkg/util/times.go

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2018 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
// Author Lars Maier
21+
//
22+
23+
package util
24+
25+
import (
26+
"math"
27+
28+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29+
)
30+
31+
// TimeCompareEqual compares two times, allowing an error of 1s
32+
func TimeCompareEqual(a, b metav1.Time) bool {
33+
return math.Abs(a.Time.Sub(b.Time).Seconds()) <= 1
34+
}
35+
36+
// TimeCompareEqualPointer compares two times, allowing an error of 1s
37+
func TimeCompareEqualPointer(a, b *metav1.Time) bool {
38+
if a == nil || b == nil {
39+
return false
40+
} else if a == b {
41+
return true
42+
}
43+
44+
return TimeCompareEqual(*a, *b)
45+
}

0 commit comments

Comments
 (0)