diff --git a/CHANGELOG.md b/CHANGELOG.md
index 67dfbf4fa..db63f922a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@
- (Bugfix) Fix Schema Apply Checksum
- (Bugfix) Use MD5 instead of SHA256 for CRD Checksums
- (Feature) (ML) Unify API
+- (Feature) (ML) Add TLS Secrets
## [1.2.40](https://github.com/arangodb/kube-arangodb/tree/1.2.40) (2024-04-10)
- (Feature) Add Core fields to the Scheduler Container Spec
diff --git a/docs/api/ArangoMLExtension.V1Alpha1.md b/docs/api/ArangoMLExtension.V1Alpha1.md
index 2cd5071d4..f1edff9b2 100644
--- a/docs/api/ArangoMLExtension.V1Alpha1.md
+++ b/docs/api/ArangoMLExtension.V1Alpha1.md
@@ -98,7 +98,7 @@ Links:
### .spec.deployment.gpu
-Type: `boolean` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.40/pkg/apis/ml/v1alpha1/extension_spec_deployment.go#L52)
+Type: `boolean` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.40/pkg/apis/ml/v1alpha1/extension_spec_deployment.go#L55)
GPU defined if GPU Jobs are enabled.
@@ -231,7 +231,7 @@ Links:
### .spec.deployment.port
-Type: `integer` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.40/pkg/apis/ml/v1alpha1/extension_spec_deployment.go#L55)
+Type: `integer` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.40/pkg/apis/ml/v1alpha1/extension_spec_deployment.go#L58)
Port defines on which port the container will be listening for connections
@@ -359,6 +359,22 @@ Links:
***
+### .spec.deployment.tls.altNames
+
+Type: `array` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.40/pkg/apis/ml/v1alpha1/extension_spec_deployment_tls.go#L28)
+
+AltNames define TLS AltNames used when TLS on the ArangoDB is enabled
+
+***
+
+### .spec.deployment.tls.enabled
+
+Type: `boolean` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.40/pkg/apis/ml/v1alpha1/extension_spec_deployment_tls.go#L25)
+
+Enabled define if TLS Should be enabled. If is not set then default is taken from ArangoDeployment settings
+
+***
+
### .spec.deployment.tolerations
Type: `[]core.Toleration` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.40/pkg/apis/scheduler/v1alpha1/pod/resources/scheduling.go#L49)
@@ -2905,6 +2921,38 @@ UID keeps the information about object UID
***
+### .status.arangoDB.tls.checksum
+
+Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.40/pkg/apis/shared/v1/object.go#L61)
+
+UID keeps the information about object Checksum
+
+***
+
+### .status.arangoDB.tls.name
+
+Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.40/pkg/apis/shared/v1/object.go#L52)
+
+Name of the object
+
+***
+
+### .status.arangoDB.tls.namespace
+
+Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.40/pkg/apis/shared/v1/object.go#L55)
+
+Namespace of the object. Should default to the namespace of the parent object
+
+***
+
+### .status.arangoDB.tls.uid
+
+Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.40/pkg/apis/shared/v1/object.go#L58)
+
+UID keeps the information about object UID
+
+***
+
### .status.conditions
Type: `api.Conditions` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.40/pkg/apis/ml/v1alpha1/extension_status.go#L31)
diff --git a/pkg/apis/ml/v1alpha1/extension_spec_deployment.go b/pkg/apis/ml/v1alpha1/extension_spec_deployment.go
index bf632ec68..809f0e04a 100644
--- a/pkg/apis/ml/v1alpha1/extension_spec_deployment.go
+++ b/pkg/apis/ml/v1alpha1/extension_spec_deployment.go
@@ -41,6 +41,9 @@ type ArangoMLExtensionSpecDeployment struct {
// Service defines how components will be exposed
Service *ArangoMLExtensionSpecDeploymentService `json:"service,omitempty"`
+ // TLS defined TLS Settings for extension
+ TLS *ArangoMLExtensionSpecDeploymentTLS `json:"tls,omitempty"`
+
// Pod defines base template for pods
*schedulerPodApi.Pod
@@ -99,6 +102,13 @@ func (s *ArangoMLExtensionSpecDeployment) GetService() *ArangoMLExtensionSpecDep
return s.Service
}
+func (s *ArangoMLExtensionSpecDeployment) GetTLS() *ArangoMLExtensionSpecDeploymentTLS {
+ if s == nil {
+ return nil
+ }
+ return s.TLS
+}
+
func (s *ArangoMLExtensionSpecDeployment) Validate() error {
if s == nil {
return nil
diff --git a/pkg/apis/ml/v1alpha1/extension_spec_deployment_tls.go b/pkg/apis/ml/v1alpha1/extension_spec_deployment_tls.go
new file mode 100644
index 000000000..242b14c1f
--- /dev/null
+++ b/pkg/apis/ml/v1alpha1/extension_spec_deployment_tls.go
@@ -0,0 +1,29 @@
+//
+// DISCLAIMER
+//
+// Copyright 2024 ArangoDB GmbH, Cologne, Germany
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Copyright holder is ArangoDB GmbH, Cologne, Germany
+//
+
+package v1alpha1
+
+type ArangoMLExtensionSpecDeploymentTLS struct {
+ // Enabled define if TLS Should be enabled. If is not set then default is taken from ArangoDeployment settings
+ Enabled *bool `json:"enabled,omitempty"`
+
+ // AltNames define TLS AltNames used when TLS on the ArangoDB is enabled
+ AltNames []string `json:"altNames,omitempty"`
+}
diff --git a/pkg/apis/ml/v1alpha1/extension_status_arangodb_ref.go b/pkg/apis/ml/v1alpha1/extension_status_arangodb_ref.go
index 7e6c5ab95..6377fb459 100644
--- a/pkg/apis/ml/v1alpha1/extension_status_arangodb_ref.go
+++ b/pkg/apis/ml/v1alpha1/extension_status_arangodb_ref.go
@@ -25,4 +25,6 @@ import sharedApi "github.com/arangodb/kube-arangodb/pkg/apis/shared/v1"
type ArangoMLExtensionStatusArangoDBRef struct {
// Secret keeps the information about ArangoDB deployment
Secret *sharedApi.Object `json:"secret,omitempty"`
+ // TLS keeps information about TLS Secret rendered from ArangoDB deployment
+ TLS *sharedApi.Object `json:"tls,omitempty"`
}
diff --git a/pkg/apis/ml/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/ml/v1alpha1/zz_generated.deepcopy.go
index 62206655c..ffde846bd 100644
--- a/pkg/apis/ml/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/ml/v1alpha1/zz_generated.deepcopy.go
@@ -380,6 +380,11 @@ func (in *ArangoMLExtensionSpecDeployment) DeepCopyInto(out *ArangoMLExtensionSp
*out = new(ArangoMLExtensionSpecDeploymentService)
(*in).DeepCopyInto(*out)
}
+ if in.TLS != nil {
+ in, out := &in.TLS, &out.TLS
+ *out = new(ArangoMLExtensionSpecDeploymentTLS)
+ (*in).DeepCopyInto(*out)
+ }
if in.Pod != nil {
in, out := &in.Pod, &out.Pod
*out = new(pod.Pod)
@@ -434,6 +439,32 @@ func (in *ArangoMLExtensionSpecDeploymentService) DeepCopy() *ArangoMLExtensionS
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ArangoMLExtensionSpecDeploymentTLS) DeepCopyInto(out *ArangoMLExtensionSpecDeploymentTLS) {
+ *out = *in
+ if in.Enabled != nil {
+ in, out := &in.Enabled, &out.Enabled
+ *out = new(bool)
+ **out = **in
+ }
+ if in.AltNames != nil {
+ in, out := &in.AltNames, &out.AltNames
+ *out = make([]string, len(*in))
+ copy(*out, *in)
+ }
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoMLExtensionSpecDeploymentTLS.
+func (in *ArangoMLExtensionSpecDeploymentTLS) DeepCopy() *ArangoMLExtensionSpecDeploymentTLS {
+ if in == nil {
+ return nil
+ }
+ out := new(ArangoMLExtensionSpecDeploymentTLS)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoMLExtensionSpecMetadataService) DeepCopyInto(out *ArangoMLExtensionSpecMetadataService) {
*out = *in
@@ -532,6 +563,11 @@ func (in *ArangoMLExtensionStatusArangoDBRef) DeepCopyInto(out *ArangoMLExtensio
*out = new(sharedv1.Object)
(*in).DeepCopyInto(*out)
}
+ if in.TLS != nil {
+ in, out := &in.TLS, &out.TLS
+ *out = new(sharedv1.Object)
+ (*in).DeepCopyInto(*out)
+ }
return
}
diff --git a/pkg/apis/shared/v1/object.go b/pkg/apis/shared/v1/object.go
index fd1ec59a1..e9cc5adf0 100644
--- a/pkg/apis/shared/v1/object.go
+++ b/pkg/apis/shared/v1/object.go
@@ -94,6 +94,20 @@ func (o *Object) GetUID() types.UID {
return ""
}
+func (o *Object) AsUIDPrecondition() *meta.Preconditions {
+ if o == nil || o.UID == nil {
+ return nil
+ }
+
+ uid := o.GetUID()
+
+ if uid == "" {
+ return nil
+ }
+
+ return meta.NewUIDPreconditions(string(uid))
+}
+
func (o *Object) GetChecksum() string {
if o != nil {
if n := o.Checksum; n != nil {
diff --git a/pkg/crd/crds/ml-extension.schema.generated.yaml b/pkg/crd/crds/ml-extension.schema.generated.yaml
index 2d34e220b..bddbf4f8c 100644
--- a/pkg/crd/crds/ml-extension.schema.generated.yaml
+++ b/pkg/crd/crds/ml-extension.schema.generated.yaml
@@ -927,6 +927,18 @@ v1alpha1:
format: int32
type: integer
type: object
+ tls:
+ description: TLS defined TLS Settings for extension
+ properties:
+ altNames:
+ description: AltNames define TLS AltNames used when TLS on the ArangoDB is enabled
+ items:
+ type: string
+ type: array
+ enabled:
+ description: Enabled define if TLS Should be enabled. If is not set then default is taken from ArangoDeployment settings
+ type: boolean
+ type: object
tolerations:
items:
properties:
diff --git a/pkg/deployment/resources/certificates_tls.go b/pkg/deployment/resources/certificates_tls.go
index 0465e53e1..d7ad24b4d 100644
--- a/pkg/deployment/resources/certificates_tls.go
+++ b/pkg/deployment/resources/certificates_tls.go
@@ -1,7 +1,7 @@
//
// DISCLAIMER
//
-// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
+// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -113,7 +113,8 @@ func createTLSServerCertificate(ctx context.Context, log logging.Logger, cachedS
strings.TrimSpace(priv)
err = globals.GetGlobalTimeouts().Kubernetes().RunWithTimeout(ctx, func(ctxChild context.Context) error {
- return k8sutil.CreateTLSKeyfileSecret(ctxChild, secrets, secretName, keyfile, ownerRef)
+ _, err := k8sutil.CreateTLSKeyfileSecret(ctxChild, secrets, secretName, keyfile, ownerRef)
+ return err
})
if err != nil {
if kerrors.IsAlreadyExists(err) {
diff --git a/pkg/util/context.go b/pkg/util/context.go
index 380d1dca4..16bb027cf 100644
--- a/pkg/util/context.go
+++ b/pkg/util/context.go
@@ -1,7 +1,7 @@
//
// DISCLAIMER
//
-// Copyright 2023 ArangoDB GmbH, Cologne, Germany
+// Copyright 2023-2024 ArangoDB GmbH, Cologne, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -64,6 +64,39 @@ func WithContextTimeoutP2A2[P1, P2, A1, A2 interface{}](ctx context.Context, tim
return f(nCtx, a1, a2)
}
+func WithKubernetesContextTimeoutP1A4[P1, A1, A2, A3, A4 interface{}](ctx context.Context, f func(context.Context, A1, A2, A3, A4) P1, a1 A1, a2 A2, a3 A3, a4 A4) P1 {
+ return WithContextTimeoutP1A4(ctx, globals.GetGlobals().Timeouts().Kubernetes().Get(), f, a1, a2, a3, a4)
+}
+
+func WithContextTimeoutP1A4[P1, A1, A2, A3, A4 interface{}](ctx context.Context, timeout time.Duration, f func(context.Context, A1, A2, A3, A4) P1, a1 A1, a2 A2, a3 A3, a4 A4) P1 {
+ nCtx, c := context.WithTimeout(ctx, timeout)
+ defer c()
+
+ return f(nCtx, a1, a2, a3, a4)
+}
+
+func WithKubernetesContextTimeoutP2A4[P1, P2, A1, A2, A3, A4 interface{}](ctx context.Context, f func(context.Context, A1, A2, A3, A4) (P1, P2), a1 A1, a2 A2, a3 A3, a4 A4) (P1, P2) {
+ return WithContextTimeoutP2A4(ctx, globals.GetGlobals().Timeouts().Kubernetes().Get(), f, a1, a2, a3, a4)
+}
+
+func WithContextTimeoutP2A4[P1, P2, A1, A2, A3, A4 interface{}](ctx context.Context, timeout time.Duration, f func(context.Context, A1, A2, A3, A4) (P1, P2), a1 A1, a2 A2, a3 A3, a4 A4) (P1, P2) {
+ nCtx, c := context.WithTimeout(ctx, timeout)
+ defer c()
+
+ return f(nCtx, a1, a2, a3, a4)
+}
+
+func WithKubernetesContextTimeoutP4A3[P1, P2, P3, P4, A1, A2, A3 interface{}](ctx context.Context, f func(context.Context, A1, A2, A3) (P1, P2, P3, P4), a1 A1, a2 A2, a3 A3) (P1, P2, P3, P4) {
+ return WithContextTimeoutP4A3(ctx, globals.GetGlobals().Timeouts().Kubernetes().Get(), f, a1, a2, a3)
+}
+
+func WithContextTimeoutP4A3[P1, P2, P3, P4, A1, A2, A3 interface{}](ctx context.Context, timeout time.Duration, f func(context.Context, A1, A2, A3) (P1, P2, P3, P4), a1 A1, a2 A2, a3 A3) (P1, P2, P3, P4) {
+ nCtx, c := context.WithTimeout(ctx, timeout)
+ defer c()
+
+ return f(nCtx, a1, a2, a3)
+}
+
type PatchInterface[P1 meta.Object] interface {
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts meta.PatchOptions, subresources ...string) (P1, error)
}
diff --git a/pkg/util/k8sutil/kerrors/errors.go b/pkg/util/k8sutil/kerrors/errors.go
index d599dc92a..98b76fe43 100644
--- a/pkg/util/k8sutil/kerrors/errors.go
+++ b/pkg/util/k8sutil/kerrors/errors.go
@@ -1,7 +1,7 @@
//
// DISCLAIMER
//
-// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
+// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -26,6 +26,47 @@ import (
"github.com/arangodb/kube-arangodb/pkg/util/errors"
)
+func Is(err error, codes ...KErrors) bool {
+ if err == nil {
+ return false
+ }
+
+ for _, code := range codes {
+ if code.Is(err) {
+ return true
+ }
+ }
+
+ return false
+}
+
+type KErrors int
+
+const (
+ AlreadyExists KErrors = iota
+ Conflict
+ Invalid
+ NotFound
+ Forbidden
+)
+
+func (k KErrors) Is(err error) bool {
+ switch k {
+ case AlreadyExists:
+ return IsAlreadyExists(err)
+ case Conflict:
+ return IsConflict(err)
+ case Invalid:
+ return IsInvalid(err)
+ case NotFound:
+ return IsNotFound(err)
+ case Forbidden:
+ return IsForbidden(err)
+ default:
+ return false
+ }
+}
+
func isError(err error, precondition func(err error) bool) bool {
if err == nil {
return false
@@ -62,6 +103,16 @@ func isConflictC(err error) bool {
return apierrors.IsConflict(err)
}
+// IsForbidden returns true if the given error is or is caused by a
+// kubernetes ForbiddenError,
+func IsForbidden(err error) bool {
+ return isError(err, isConflictC)
+}
+
+func IsForbiddenC(err error) bool {
+ return apierrors.IsForbidden(err)
+}
+
// IsNotFound returns true if the given error is or is caused by a
// kubernetes NotFoundError,
func IsNotFound(err error) bool {
diff --git a/pkg/util/k8sutil/secrets.go b/pkg/util/k8sutil/secrets.go
index 6dfb68146..a17a5fa74 100644
--- a/pkg/util/k8sutil/secrets.go
+++ b/pkg/util/k8sutil/secrets.go
@@ -216,7 +216,7 @@ func GetTLSKeyfileFromSecret(s *core.Secret) (string, error) {
// CreateTLSKeyfileSecret creates a secret used to store a PEM encoded keyfile
// in the format ArangoDB accepts it for its `--ssl.keyfile` option.
func CreateTLSKeyfileSecret(ctx context.Context, secrets secretv1.ModInterface, secretName string, keyfile string,
- ownerRef *meta.OwnerReference) error {
+ ownerRef *meta.OwnerReference) (*core.Secret, error) {
// Create secret
secret := &core.Secret{
ObjectMeta: meta.ObjectMeta{
@@ -228,11 +228,12 @@ func CreateTLSKeyfileSecret(ctx context.Context, secrets secretv1.ModInterface,
}
// Attach secret to owner
AddOwnerRefToObject(secret, ownerRef)
- if _, err := secrets.Create(ctx, secret, meta.CreateOptions{}); err != nil {
+ if s, err := secrets.Create(ctx, secret, meta.CreateOptions{}); err != nil {
// Failed to create secret
- return kerrors.NewResourceError(err, secret)
+ return nil, kerrors.NewResourceError(err, secret)
+ } else {
+ return s, nil
}
- return nil
}
// ValidateTokenSecret checks that a secret with given name in given namespace