Skip to content

Commit 2d47ee1

Browse files
authored
[Feature] Update Propagated flags (#597)
1 parent 05351b1 commit 2d47ee1

File tree

17 files changed

+441
-84
lines changed

17 files changed

+441
-84
lines changed

pkg/apis/deployment/v1/hashes.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,15 @@ type DeploymentStatusHashes struct {
3232

3333
type DeploymentStatusHashesEncryption struct {
3434
Keys shared.HashList `json:"keys,omitempty"`
35+
36+
Propagated bool `json:"propagated,omitempty"`
3537
}
3638

3739
type DeploymentStatusHashesTLS struct {
3840
CA *string `json:"ca,omitempty"`
3941
Truststore shared.HashList `json:"truststore,omitempty"`
42+
43+
Propagated bool `json:"propagated,omitempty"`
4044
}
4145

4246
type DeploymentStatusHashesJWT struct {

pkg/apis/deployment/v1/plan.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ const (
7575
ActionTypeRefreshTLSKeyfileCertificate ActionType = "RefreshTLSKeyfileCertificate"
7676
// ActionTypeTLSKeyStatusUpdate update status with current data from deployment
7777
ActionTypeTLSKeyStatusUpdate ActionType = "TLSKeyStatusUpdate"
78+
// ActionTypeTLSPropagated change propagated flag
79+
ActionTypeTLSPropagated ActionType = "TLSPropagated"
7880
// ActionTypeUpdateTLSSNI update SNI inplace.
7981
ActionTypeUpdateTLSSNI ActionType = "UpdateTLSSNI"
8082
// ActionTypeSetCurrentImage causes status.CurrentImage to be updated to the image given in the action.
@@ -101,6 +103,8 @@ const (
101103
ActionTypeEncryptionKeyRefresh ActionType = "EncryptionKeyRefresh"
102104
// ActionTypeEncryptionKeyStatusUpdate update status object with current encryption keys
103105
ActionTypeEncryptionKeyStatusUpdate ActionType = "EncryptionKeyStatusUpdate"
106+
// ActionTypeEncryptionKeyPropagated change propagated flag
107+
ActionTypeEncryptionKeyPropagated ActionType = "EncryptionKeyPropagated"
104108
// ActionTypeJWTStatusUpdate update status of JWT Secret
105109
ActionTypeJWTStatusUpdate ActionType = "JWTStatusUpdate"
106110
// ActionTypeJWTSetActive change active JWT key

pkg/deployment/pod/encryption.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,12 @@ func GetEncryptionKey(secrets k8sutil.SecretInterface, name string) (string, []b
7878

7979
func GetEncryptionKeyFromSecret(keyfile *core.Secret) (string, []byte, error) {
8080
if len(keyfile.Data) == 0 {
81-
return "", nil, nil
81+
return "", nil, errors.Errorf("Current encryption key is not valid - missing data section")
8282
}
8383

8484
d, ok := keyfile.Data[constants.SecretEncryptionKey]
8585
if !ok {
86-
return "", nil, nil
86+
return "", nil, errors.Errorf("Current encryption key is not valid - missing field")
8787
}
8888

8989
if len(d) != 32 {

pkg/deployment/reconcile/action_encryption_add.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func (a *encryptionKeyAddAction) Start(ctx context.Context) (bool, error) {
7878
}
7979

8080
secret := a.actionCtx.GetSpec().RocksDB.Encryption.GetKeySecretName()
81-
if s, ok := a.action.Params["secret"]; ok {
81+
if s, ok := a.action.Params[secretActionParam]; ok {
8282
secret = s
8383
}
8484

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2020 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 Adam Janikowski
21+
//
22+
23+
package reconcile
24+
25+
import (
26+
"context"
27+
28+
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
29+
"github.com/rs/zerolog"
30+
)
31+
32+
func init() {
33+
registerAction(api.ActionTypeEncryptionKeyPropagated, newEncryptionKeyPropagated)
34+
}
35+
36+
func newEncryptionKeyPropagated(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
37+
a := &encryptionKeyPropagatedAction{}
38+
39+
a.actionImpl = newActionImplDefRef(log, action, actionCtx, defaultTimeout)
40+
41+
return a
42+
}
43+
44+
type encryptionKeyPropagatedAction struct {
45+
actionImpl
46+
47+
actionEmptyCheckProgress
48+
}
49+
50+
func (a *encryptionKeyPropagatedAction) Start(ctx context.Context) (bool, error) {
51+
propagatedFlag, exists := a.action.Params[propagated]
52+
if !exists {
53+
a.log.Error().Msgf("Propagated flag is missing")
54+
return true, nil
55+
}
56+
57+
propagatedFlagBool := propagatedFlag == conditionTrue
58+
59+
if err := a.actionCtx.WithStatusUpdate(func(s *api.DeploymentStatus) bool {
60+
if s.Hashes.Encryption.Propagated != propagatedFlagBool {
61+
s.Hashes.Encryption.Propagated = propagatedFlagBool
62+
return true
63+
}
64+
65+
return false
66+
}); err != nil {
67+
return false, err
68+
}
69+
70+
return true, nil
71+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2020 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 Adam Janikowski
21+
//
22+
23+
package reconcile
24+
25+
import (
26+
"context"
27+
28+
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
29+
"github.com/rs/zerolog"
30+
)
31+
32+
func init() {
33+
registerAction(api.ActionTypeTLSPropagated, newTLSPropagated)
34+
}
35+
36+
func newTLSPropagated(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
37+
a := &tlsPropagatedAction{}
38+
39+
a.actionImpl = newActionImplDefRef(log, action, actionCtx, defaultTimeout)
40+
41+
return a
42+
}
43+
44+
type tlsPropagatedAction struct {
45+
actionImpl
46+
47+
actionEmptyCheckProgress
48+
}
49+
50+
func (a *tlsPropagatedAction) Start(ctx context.Context) (bool, error) {
51+
propagatedFlag, exists := a.action.Params[propagated]
52+
if !exists {
53+
a.log.Error().Msgf("Propagated flag is missing")
54+
return true, nil
55+
}
56+
57+
propagatedFlagBool := propagatedFlag == conditionTrue
58+
59+
if err := a.actionCtx.WithStatusUpdate(func(s *api.DeploymentStatus) bool {
60+
if s.Hashes.TLS.Propagated != propagatedFlagBool {
61+
s.Hashes.TLS.Propagated = propagatedFlagBool
62+
return true
63+
}
64+
65+
return false
66+
}); err != nil {
67+
return false, err
68+
}
69+
70+
return true, nil
71+
}

pkg/deployment/reconcile/plan_builder.go

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ func createPlan(ctx context.Context, log zerolog.Logger, apiObject k8sutil.APIOb
203203

204204
// Update status
205205
if plan.IsEmpty() {
206-
plan = pb.Apply(createEncryptionKeyStatusUpdate)
206+
plan = pb.ApplySubPlan(createEncryptionKeyStatusPropagatedFieldUpdate, createEncryptionKeyStatusUpdate)
207207
}
208208

209209
if plan.IsEmpty() {
@@ -226,19 +226,19 @@ func createPlan(ctx context.Context, log zerolog.Logger, apiObject k8sutil.APIOb
226226

227227
// Add keys
228228
if plan.IsEmpty() {
229-
plan = pb.Apply(createEncryptionKey)
229+
plan = pb.ApplySubPlan(createEncryptionKeyStatusPropagatedFieldUpdate, createEncryptionKey)
230230
}
231231

232232
if plan.IsEmpty() {
233233
plan = pb.Apply(createJWTKeyUpdate)
234234
}
235235

236236
if plan.IsEmpty() {
237-
plan = pb.Apply(createCARenewalPlan)
237+
plan = pb.ApplySubPlan(createTLSStatusPropagatedFieldUpdate, createCARenewalPlan)
238238
}
239239

240240
if plan.IsEmpty() {
241-
plan = pb.Apply(createCAAppendPlan)
241+
plan = pb.ApplySubPlan(createTLSStatusPropagatedFieldUpdate, createCAAppendPlan)
242242
}
243243

244244
if plan.IsEmpty() {
@@ -251,25 +251,31 @@ func createPlan(ctx context.Context, log zerolog.Logger, apiObject k8sutil.APIOb
251251
}
252252

253253
if plan.IsEmpty() {
254-
plan = pb.Apply(createRotateTLSServerSNIPlan)
254+
plan = pb.ApplySubPlan(createTLSStatusPropagatedFieldUpdate, createRotateTLSServerSNIPlan)
255255
}
256256

257257
if plan.IsEmpty() {
258258
plan = pb.Apply(createRestorePlan)
259259
}
260260

261261
if plan.IsEmpty() {
262-
plan = pb.Apply(createEncryptionKeyCleanPlan)
262+
plan = pb.ApplySubPlan(createEncryptionKeyStatusPropagatedFieldUpdate, createEncryptionKeyCleanPlan)
263263
}
264264

265265
if plan.IsEmpty() {
266-
plan = pb.Apply(createCACleanPlan)
266+
plan = pb.ApplySubPlan(createTLSStatusPropagatedFieldUpdate, createCACleanPlan)
267267
}
268268

269269
if plan.IsEmpty() {
270270
plan = pb.Apply(createClusterOperationPlan)
271271
}
272272

273+
// Final
274+
275+
if plan.IsEmpty() {
276+
plan = pb.Apply(createTLSStatusPropagated)
277+
}
278+
273279
// Return plan
274280
return plan, true
275281
}
@@ -296,6 +302,11 @@ type planBuilder func(ctx context.Context,
296302
spec api.DeploymentSpec, status api.DeploymentStatus,
297303
cachedStatus inspector.Inspector, context PlanBuilderContext) api.Plan
298304

305+
type planBuilderSubPlan func(ctx context.Context,
306+
log zerolog.Logger, apiObject k8sutil.APIObject,
307+
spec api.DeploymentSpec, status api.DeploymentStatus,
308+
cachedStatus inspector.Inspector, context PlanBuilderContext, w WithPlanBuilder, plans ...planBuilder) api.Plan
309+
299310
func NewWithPlanBuilder(ctx context.Context,
300311
log zerolog.Logger, apiObject k8sutil.APIObject,
301312
spec api.DeploymentSpec, status api.DeploymentStatus,
@@ -313,6 +324,7 @@ func NewWithPlanBuilder(ctx context.Context,
313324

314325
type WithPlanBuilder interface {
315326
Apply(p planBuilder) api.Plan
327+
ApplySubPlan(p planBuilderSubPlan, plans ...planBuilder) api.Plan
316328
}
317329

318330
type withPlanBuilder struct {
@@ -325,6 +337,10 @@ type withPlanBuilder struct {
325337
context PlanBuilderContext
326338
}
327339

340+
func (w withPlanBuilder) ApplySubPlan(p planBuilderSubPlan, plans ...planBuilder) api.Plan {
341+
return p(w.ctx, w.log, w.apiObject, w.spec, w.status, w.cachedStatus, w.context, w, plans...)
342+
}
343+
328344
func (w withPlanBuilder) Apply(p planBuilder) api.Plan {
329345
return p(w.ctx, w.log, w.apiObject, w.spec, w.status, w.cachedStatus, w.context)
330346
}

pkg/deployment/reconcile/plan_builder_encryption.go

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,43 @@ func skipEncryptionPlan(spec api.DeploymentSpec, status api.DeploymentStatus) bo
5252
return false
5353
}
5454

55+
func createEncryptionKeyStatusPropagatedFieldUpdate(ctx context.Context,
56+
log zerolog.Logger, apiObject k8sutil.APIObject,
57+
spec api.DeploymentSpec, status api.DeploymentStatus,
58+
cachedStatus inspector.Inspector, context PlanBuilderContext, w WithPlanBuilder, builders ...planBuilder) api.Plan {
59+
if skipEncryptionPlan(spec, status) {
60+
return nil
61+
}
62+
63+
var plan api.Plan
64+
65+
for _, builder := range builders {
66+
if !plan.IsEmpty() {
67+
continue
68+
}
69+
70+
if p := w.Apply(builder); !p.IsEmpty() {
71+
plan = append(plan, p...)
72+
}
73+
}
74+
75+
if plan.IsEmpty() {
76+
return nil
77+
}
78+
79+
if len(plan) == 1 && plan[0].Type == api.ActionTypeEncryptionKeyPropagated {
80+
return plan
81+
}
82+
83+
if status.Hashes.Encryption.Propagated {
84+
plan = append(api.Plan{
85+
api.NewAction(api.ActionTypeEncryptionKeyPropagated, api.ServerGroupUnknown, "", "Change propagated flag to false").AddParam(propagated, conditionFalse),
86+
}, plan...)
87+
}
88+
89+
return plan
90+
}
91+
5592
func createEncryptionKey(ctx context.Context,
5693
log zerolog.Logger, apiObject k8sutil.APIObject,
5794
spec api.DeploymentSpec, status api.DeploymentStatus,
@@ -85,17 +122,24 @@ func createEncryptionKey(ctx context.Context,
85122
keyfolder.Data = map[string][]byte{}
86123
}
87124

88-
_, ok := keyfolder.Data[name]
89-
if !ok {
90-
return api.Plan{api.NewAction(api.ActionTypeEncryptionKeyAdd, api.ServerGroupUnknown, "")}
125+
if status.Hashes.Encryption.Propagated {
126+
_, ok := keyfolder.Data[name]
127+
if !ok {
128+
return api.Plan{api.NewAction(api.ActionTypeEncryptionKeyAdd, api.ServerGroupUnknown, "")}
129+
}
91130
}
92131

93-
plan, _ := areEncryptionKeysUpToDate(ctx, log, apiObject, spec, status, cachedStatus, context, keyfolder)
94-
132+
plan, failed := areEncryptionKeysUpToDate(ctx, log, apiObject, spec, status, cachedStatus, context, keyfolder)
95133
if !plan.IsEmpty() {
96134
return plan
97135
}
98136

137+
if !failed && !status.Hashes.Encryption.Propagated {
138+
return api.Plan{
139+
api.NewAction(api.ActionTypeEncryptionKeyPropagated, api.ServerGroupUnknown, "", "Change propagated flag to true").AddParam(propagated, conditionTrue),
140+
}
141+
}
142+
99143
return api.Plan{}
100144
}
101145

@@ -152,17 +196,11 @@ func createEncryptionKeyCleanPlan(ctx context.Context,
152196
return nil
153197
}
154198

155-
plan, failed := areEncryptionKeysUpToDate(ctx, log, apiObject, spec, status, cachedStatus, context, keyfolder)
156-
157-
if failed {
158-
log.Info().Msgf("Unable to continue with encryption until all servers are ready")
199+
if !status.Hashes.Encryption.Propagated {
159200
return nil
160201
}
161202

162-
if len(plan) != 0 {
163-
log.Info().Msgf("Unable to continue with encryption until all servers report state or gonna be upToDate")
164-
return nil
165-
}
203+
var plan api.Plan
166204

167205
if len(keyfolder.Data) <= 1 {
168206
return nil

0 commit comments

Comments
 (0)