Skip to content

Commit 2c83d5c

Browse files
committed
[Feature] [ML] Enable TLS
1 parent 687f649 commit 2c83d5c

File tree

7 files changed

+549
-4
lines changed

7 files changed

+549
-4
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
- (Feature) (ML) Unify API
1010
- (Feature) (ML) Add TLS Secrets
1111
- (Feature) (ML) Allow to change API port
12+
- (Feature) (ML) Enable TLS
1213

1314
## [1.2.40](https://github.com/arangodb/kube-arangodb/tree/1.2.40) (2024-04-10)
1415
- (Feature) Add Core fields to the Scheduler Container Spec

pkg/apis/ml/v1alpha1/conditions.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2023-2024 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -32,6 +32,7 @@ const (
3232
ExtensionMetadataServiceValidCondition api.ConditionType = "MetadataServiceValid"
3333
ExtensionServiceAccountReadyCondition api.ConditionType = "ServiceAccountReady"
3434
ExtensionStatefulSetReadyCondition api.ConditionType = "ExtensionDeploymentReady"
35+
ExtensionTLSEnabledCondition api.ConditionType = "TLSEnabled"
3536
LicenseValidCondition api.ConditionType = "LicenseValid"
3637
CronJobSyncedCondition api.ConditionType = "CronJobSynced"
3738
BatchJobSyncedCondition api.ConditionType = "BatchJobSynced"

pkg/apis/ml/v1alpha1/extension_spec_deployment_tls.go

+16
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,19 @@ type ArangoMLExtensionSpecDeploymentTLS struct {
2727
// AltNames define TLS AltNames used when TLS on the ArangoDB is enabled
2828
AltNames []string `json:"altNames,omitempty"`
2929
}
30+
31+
func (a *ArangoMLExtensionSpecDeploymentTLS) IsEnabled() bool {
32+
if a == nil || a.Enabled == nil {
33+
return true
34+
}
35+
36+
return *a.Enabled
37+
}
38+
39+
func (a *ArangoMLExtensionSpecDeploymentTLS) GetAltNames() []string {
40+
if a == nil || a.AltNames == nil {
41+
return nil
42+
}
43+
44+
return a.AltNames
45+
}

pkg/util/k8sutil/helpers/updator.go

+244
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2024 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+
21+
package helpers
22+
23+
import (
24+
"context"
25+
26+
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
27+
28+
sharedApi "github.com/arangodb/kube-arangodb/pkg/apis/shared/v1"
29+
"github.com/arangodb/kube-arangodb/pkg/logging"
30+
operator "github.com/arangodb/kube-arangodb/pkg/operatorV2"
31+
"github.com/arangodb/kube-arangodb/pkg/util"
32+
"github.com/arangodb/kube-arangodb/pkg/util/errors"
33+
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil/kerrors"
34+
)
35+
36+
type Action int
37+
38+
func (a Action) Or(b Action) Action {
39+
if b > a {
40+
return b
41+
}
42+
43+
return a
44+
}
45+
46+
const (
47+
ActionOK Action = iota
48+
ActionReplace
49+
ActionUpdate
50+
)
51+
52+
type Object interface {
53+
comparable
54+
meta.Object
55+
}
56+
57+
type Client[T Object] interface {
58+
Get(ctx context.Context, name string, options meta.GetOptions) (T, error)
59+
Update(ctx context.Context, object T, options meta.UpdateOptions) (T, error)
60+
Create(ctx context.Context, object T, options meta.CreateOptions) (T, error)
61+
Delete(ctx context.Context, name string, options meta.DeleteOptions) error
62+
}
63+
64+
type Generate[T Object] func(ctx context.Context, ref *sharedApi.Object) (T, bool, string, error)
65+
66+
func OperatorUpdate[T Object](ctx context.Context, logger logging.Logger, client Client[T], ref **sharedApi.Object, generator Generate[T], decisions ...Decision[T]) (bool, error) {
67+
changed, err := Update[T](ctx, logger, client, ref, generator, decisions...)
68+
if err != nil {
69+
return false, err
70+
}
71+
72+
if changed {
73+
return true, operator.Reconcile("Change in resources")
74+
}
75+
76+
return false, nil
77+
}
78+
79+
func Update[T Object](ctx context.Context, logger logging.Logger, client Client[T], ref **sharedApi.Object, generator Generate[T], decisions ...Decision[T]) (bool, error) {
80+
decision := Decision[T](EmptyDecision[T]).With(decisions...)
81+
82+
if ref == nil {
83+
return false, errors.Errorf("Reference is nil")
84+
}
85+
86+
currentRef := *ref
87+
88+
var discoveredObject T
89+
var discoveredObjectExists bool
90+
91+
if currentRef != nil {
92+
object, err := util.WithKubernetesContextTimeoutP2A2(ctx, client.Get, currentRef.GetName(), meta.GetOptions{})
93+
if err != nil {
94+
if !kerrors.Is(err, kerrors.NotFound) {
95+
return false, err
96+
}
97+
98+
*ref = nil
99+
logger.
100+
Str("name", currentRef.GetName()).
101+
Str("checksum", currentRef.GetChecksum()).
102+
Str("uid", string(currentRef.GetUID())).
103+
Debug("Object has been removed")
104+
105+
return true, nil
106+
}
107+
108+
if object.GetDeletionTimestamp() != nil {
109+
// Object is currently deleting
110+
logger.
111+
Str("name", currentRef.GetName()).
112+
Str("checksum", currentRef.GetChecksum()).
113+
Str("uid", string(currentRef.GetUID())).
114+
Debug("Object is currently deleting")
115+
return true, nil
116+
}
117+
118+
if object.GetUID() != currentRef.GetUID() {
119+
logger.
120+
Str("name", currentRef.GetName()).
121+
Str("checksum", currentRef.GetChecksum()).
122+
Str("uid", string(currentRef.GetUID())).
123+
Warn("Recreation Required as UID changed")
124+
125+
if err := util.WithKubernetesContextTimeoutP1A2(ctx, client.Delete, currentRef.GetName(), meta.DeleteOptions{}); err != nil {
126+
if !kerrors.Is(err, kerrors.NotFound) {
127+
return false, err
128+
}
129+
}
130+
131+
return true, nil
132+
}
133+
134+
discoveredObject = object
135+
discoveredObjectExists = true
136+
}
137+
138+
object, skip, checksum, err := generator(ctx, currentRef.DeepCopy())
139+
if err != nil {
140+
return false, err
141+
}
142+
143+
if skip {
144+
// Skip update as it is not required
145+
return false, nil
146+
}
147+
148+
if object == util.Default[T]() {
149+
// Object is supposed to be removed
150+
if currentRef == nil {
151+
// Nothing to do
152+
return false, nil
153+
}
154+
155+
// Remove object
156+
if err := util.WithKubernetesContextTimeoutP1A2(ctx, client.Delete, currentRef.GetName(), meta.DeleteOptions{}); err != nil {
157+
if !kerrors.Is(err, kerrors.NotFound) {
158+
return false, err
159+
}
160+
}
161+
162+
logger.
163+
Str("name", currentRef.GetName()).
164+
Str("checksum", currentRef.GetChecksum()).
165+
Str("uid", string(currentRef.GetUID())).
166+
Info("Object deletion has been requested")
167+
168+
return true, nil
169+
}
170+
171+
if !discoveredObjectExists {
172+
// Let's create Object
173+
newObject, err := util.WithKubernetesContextTimeoutP2A2(ctx, client.Create, object, meta.CreateOptions{})
174+
if err != nil {
175+
return false, err
176+
}
177+
178+
currentRef = util.NewType(sharedApi.NewObjectWithChecksum(newObject, checksum))
179+
*ref = currentRef
180+
logger.
181+
Str("name", currentRef.GetName()).
182+
Str("checksum", currentRef.GetChecksum()).
183+
Str("uid", string(currentRef.GetUID())).
184+
Info("Object has been created")
185+
186+
return true, nil
187+
}
188+
189+
// Object exists, lets check if update is required
190+
action, err := decision(ctx, DecisionObject[T]{
191+
Checksum: currentRef.GetChecksum(),
192+
Object: discoveredObject,
193+
}, DecisionObject[T]{
194+
Checksum: checksum,
195+
Object: object,
196+
})
197+
if err != nil {
198+
return false, err
199+
}
200+
201+
switch action {
202+
case ActionOK:
203+
// Nothing to do
204+
return false, nil
205+
case ActionReplace:
206+
// Object needs to be removed
207+
logger.
208+
Str("name", currentRef.GetName()).
209+
Str("checksum", currentRef.GetChecksum()).
210+
Str("uid", string(currentRef.GetUID())).
211+
Info("Object needs to be replaced")
212+
213+
if err := util.WithKubernetesContextTimeoutP1A2(ctx, client.Delete, currentRef.GetName(), meta.DeleteOptions{}); err != nil {
214+
if !kerrors.Is(err, kerrors.NotFound) {
215+
return false, err
216+
}
217+
}
218+
219+
return true, nil
220+
case ActionUpdate:
221+
logger.
222+
Str("name", currentRef.GetName()).
223+
Str("checksum", currentRef.GetChecksum()).
224+
Str("uid", string(currentRef.GetUID())).
225+
Info("Object needs to be updated in-place")
226+
227+
newObject, err := util.WithKubernetesContextTimeoutP2A2(ctx, client.Update, object, meta.UpdateOptions{})
228+
if err != nil {
229+
if !kerrors.Is(err, kerrors.NotFound) {
230+
return false, err
231+
}
232+
233+
// Reconcile if object was not found
234+
return true, nil
235+
}
236+
237+
*ref = util.NewType(sharedApi.NewObjectWithChecksum(newObject, checksum))
238+
239+
return true, nil
240+
241+
default:
242+
return false, errors.Errorf("Unknown action returned")
243+
}
244+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2024 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+
21+
package helpers
22+
23+
import (
24+
"context"
25+
"reflect"
26+
)
27+
28+
type DecisionObject[T Object] struct {
29+
Checksum string
30+
Object T
31+
}
32+
33+
func EmptyDecision[T Object](ctx context.Context, current, expected DecisionObject[T]) (Action, error) {
34+
return ActionOK, nil
35+
}
36+
37+
type Decision[T Object] func(ctx context.Context, current, expected DecisionObject[T]) (Action, error)
38+
39+
func (d Decision[T]) Call(ctx context.Context, current, expected DecisionObject[T]) (Action, error) {
40+
if d == nil {
41+
return EmptyDecision[T](ctx, current, expected)
42+
}
43+
44+
return d(ctx, current, expected)
45+
}
46+
47+
func (d Decision[T]) With(other ...Decision[T]) Decision[T] {
48+
return func(ctx context.Context, current, expected DecisionObject[T]) (Action, error) {
49+
action, err := d.Call(ctx, current, expected)
50+
if err != nil {
51+
return 0, err
52+
}
53+
54+
for _, o := range other {
55+
if action == ActionReplace {
56+
return ActionReplace, nil
57+
}
58+
59+
otherAction, err := o.Call(ctx, current, expected)
60+
if err != nil {
61+
return 0, err
62+
}
63+
64+
action = action.Or(otherAction)
65+
}
66+
67+
return action, nil
68+
}
69+
}
70+
71+
func ReplaceChecksum[T Object](ctx context.Context, current, expected DecisionObject[T]) (Action, error) {
72+
if current.Checksum != expected.Checksum {
73+
return ActionReplace, nil
74+
}
75+
76+
return ActionOK, nil
77+
}
78+
79+
func UpdateOwnerReference[T Object](ctx context.Context, current, expected DecisionObject[T]) (Action, error) {
80+
if !reflect.DeepEqual(current.Object.GetOwnerReferences(), expected.Object.GetOwnerReferences()) {
81+
return ActionUpdate, nil
82+
}
83+
84+
return ActionOK, nil
85+
}

0 commit comments

Comments
 (0)