Skip to content

Commit 757589f

Browse files
committed
Merge branch 'master' into deployment-phase
2 parents 4acc907 + d981d31 commit 757589f

File tree

12 files changed

+331
-6
lines changed

12 files changed

+331
-6
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,8 @@ run-unit-tests: $(GOBUILDDIR) $(SOURCES)
216216
golang:$(GOVERSION) \
217217
go test $(TESTVERBOSEOPTIONS) \
218218
$(REPOPATH)/pkg/apis/deployment/v1alpha \
219-
$(REPOPATH)/pkg/deployment \
220219
$(REPOPATH)/pkg/deployment/reconcile \
220+
$(REPOPATH)/pkg/deployment/resources \
221221
$(REPOPATH)/pkg/util/k8sutil \
222222
$(REPOPATH)/pkg/util/k8sutil/test
223223

pkg/apis/deployment/v1alpha/conditions.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ const (
3737
ConditionTypeTerminated ConditionType = "Terminated"
3838
// ConditionTypeAutoUpgrade indicates that the member has to be started with `--database.auto-upgrade` once.
3939
ConditionTypeAutoUpgrade ConditionType = "AutoUpgrade"
40+
// ConditionTypeSecretsChanged indicates that the value of one of more secrets used by
41+
// the deployment have changed. Once that is the case, the operator will no longer
42+
// touch the deployment, until the original secrets have been restored.
43+
ConditionTypeSecretsChanged ConditionType = "SecretsChanged"
4044
)
4145

4246
// Condition represents one current condition of a deployment or deployment member.

pkg/apis/deployment/v1alpha/deployment.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,11 @@ type ArangoDeployment struct {
5050

5151
// AsOwner creates an OwnerReference for the given deployment
5252
func (d *ArangoDeployment) AsOwner() metav1.OwnerReference {
53-
controller := true
5453
return metav1.OwnerReference{
5554
APIVersion: SchemeGroupVersion.String(),
5655
Kind: ArangoDeploymentResourceKind,
5756
Name: d.Name,
5857
UID: d.UID,
59-
Controller: &controller,
6058
}
6159
}
6260

pkg/apis/deployment/v1alpha/deployment_status.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,8 @@ type DeploymentStatus struct {
5050

5151
// AcceptedSpec contains the last specification that was accepted by the operator.
5252
AcceptedSpec *DeploymentSpec `json:"accepted-spec,omitempty"`
53+
54+
// SecretHashes keeps a sha256 hash of secret values, so we can
55+
// detect changes in secret values.
56+
SecretHashes *SecretHashes `json:"secret-hashes,omitempty"`
5357
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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 Ewout Prangsma
21+
//
22+
23+
package v1alpha
24+
25+
// SecretHashes keeps track of the value of secrets
26+
// so we can detect changes.
27+
// For each used secret, a sha256 hash is stored.
28+
type SecretHashes struct {
29+
// AuthJWT contains the hash of the auth.jwtSecretName secret
30+
AuthJWT string `json:"auth-jwt,omitempty"`
31+
// RocksDBEncryptionKey contains the hash of the rocksdb.encryption.keySecretName secret
32+
RocksDBEncryptionKey string `json:"rocksdb-encryption-key,omitempty"`
33+
// TLSCA contains the hash of the tls.caSecretName secret
34+
TLSCA string `json:"tls-ca,omitempty"`
35+
// SyncTLSCA contains the hash of the sync.tls.caSecretName secret
36+
SyncTLSCA string `json:"sync-tls-ca,omitempty"`
37+
}

pkg/apis/deployment/v1alpha/zz_generated.deepcopy.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,15 @@ func (in *DeploymentStatus) DeepCopyInto(out *DeploymentStatus) {
265265
(*in).DeepCopyInto(*out)
266266
}
267267
}
268+
if in.SecretHashes != nil {
269+
in, out := &in.SecretHashes, &out.SecretHashes
270+
if *in == nil {
271+
*out = nil
272+
} else {
273+
*out = new(SecretHashes)
274+
**out = **in
275+
}
276+
}
268277
return
269278
}
270279

@@ -442,6 +451,22 @@ func (in *RocksDBSpec) DeepCopy() *RocksDBSpec {
442451
return out
443452
}
444453

454+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
455+
func (in *SecretHashes) DeepCopyInto(out *SecretHashes) {
456+
*out = *in
457+
return
458+
}
459+
460+
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretHashes.
461+
func (in *SecretHashes) DeepCopy() *SecretHashes {
462+
if in == nil {
463+
return nil
464+
}
465+
out := new(SecretHashes)
466+
in.DeepCopyInto(out)
467+
return out
468+
}
469+
445470
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
446471
func (in *ServerGroupSpec) DeepCopyInto(out *ServerGroupSpec) {
447472
*out = *in

pkg/apis/storage/v1alpha/local_storage.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,10 @@ type ArangoLocalStorage struct {
5252

5353
// AsOwner creates an OwnerReference for the given storage
5454
func (d *ArangoLocalStorage) AsOwner() metav1.OwnerReference {
55-
controller := true
5655
return metav1.OwnerReference{
5756
APIVersion: SchemeGroupVersion.String(),
5857
Kind: ArangoLocalStorageResourceKind,
5958
Name: d.Name,
6059
UID: d.UID,
61-
Controller: &controller,
6260
}
6361
}

pkg/deployment/deployment.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ func New(config Config, deps Dependencies, apiObject *api.ArangoDeployment) (*De
120120
go d.run()
121121
go d.listenForPodEvents(d.stopCh)
122122
go d.listenForPVCEvents(d.stopCh)
123+
go d.listenForSecretEvents(d.stopCh)
123124
go d.listenForServiceEvents(d.stopCh)
124125
if apiObject.Spec.GetMode() == api.DeploymentModeCluster {
125126
ci := newClusterScalingIntegration(d)

pkg/deployment/deployment_inspector.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"context"
2727
"time"
2828

29+
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha"
2930
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
3031
)
3132

@@ -37,12 +38,30 @@ import (
3738
// - once in a while
3839
// Returns the delay until this function should be called again.
3940
func (d *Deployment) inspectDeployment(lastInterval time.Duration) time.Duration {
40-
// log := d.deps.Log
41+
log := d.deps.Log
4142

4243
nextInterval := lastInterval
4344
hasError := false
4445
ctx := context.Background()
4546

47+
// Is the deployment in failed state, if so, give up.
48+
if d.status.State == api.DeploymentStateFailed {
49+
log.Debug().Msg("Deployment is in Failed state.")
50+
return nextInterval
51+
}
52+
53+
// Inspect secret hashes
54+
if err := d.resources.ValidateSecretHashes(); err != nil {
55+
hasError = true
56+
d.CreateEvent(k8sutil.NewErrorEvent("Secret hash validation failed", err, d.apiObject))
57+
}
58+
59+
// Is the deployment in a good state?
60+
if d.status.Conditions.IsTrue(api.ConditionTypeSecretsChanged) {
61+
log.Debug().Msg("Condition SecretsChanged is true. Revert secrets before we can continue")
62+
return nextInterval
63+
}
64+
4665
// Ensure we have image info
4766
if retrySoon, err := d.ensureImages(d.apiObject); err != nil {
4867
hasError = true

pkg/deployment/informers.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,49 @@ func (d *Deployment) listenForPVCEvents(stopCh <-chan struct{}) {
112112
informer.Run(stopCh)
113113
}
114114

115+
// listenForSecretEvents keep listening for changes in Secrets's until the given channel is closed.
116+
func (d *Deployment) listenForSecretEvents(stopCh <-chan struct{}) {
117+
source := cache.NewListWatchFromClient(
118+
d.deps.KubeCli.CoreV1().RESTClient(),
119+
"secrets",
120+
d.apiObject.GetNamespace(),
121+
fields.Everything())
122+
123+
getSecret := func(obj interface{}) (*v1.Secret, bool) {
124+
secret, ok := obj.(*v1.Secret)
125+
if !ok {
126+
tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
127+
if !ok {
128+
return nil, false
129+
}
130+
secret, ok = tombstone.Obj.(*v1.Secret)
131+
return secret, ok
132+
}
133+
return secret, true
134+
}
135+
136+
_, informer := cache.NewIndexerInformer(source, &v1.Secret{}, 0, cache.ResourceEventHandlerFuncs{
137+
// Note: For secrets we look at all of them because they do not have to be owned by this deployment.
138+
AddFunc: func(obj interface{}) {
139+
if _, ok := getSecret(obj); ok {
140+
d.triggerInspection()
141+
}
142+
},
143+
UpdateFunc: func(oldObj, newObj interface{}) {
144+
if _, ok := getSecret(newObj); ok {
145+
d.triggerInspection()
146+
}
147+
},
148+
DeleteFunc: func(obj interface{}) {
149+
if _, ok := getSecret(obj); ok {
150+
d.triggerInspection()
151+
}
152+
},
153+
}, cache.Indexers{})
154+
155+
informer.Run(stopCh)
156+
}
157+
115158
// listenForServiceEvents keep listening for changes in Service's until the given channel is closed.
116159
func (d *Deployment) listenForServiceEvents(stopCh <-chan struct{}) {
117160
source := cache.NewListWatchFromClient(

0 commit comments

Comments
 (0)