1
0
Fork 0
mirror of https://github.com/arangodb/kube-arangodb.git synced 2024-12-14 11:57:37 +00:00

[Feature] Add ArangoDeployment ServerGroupType (#1699)

This commit is contained in:
Adam Janikowski 2024-08-22 14:02:36 +02:00 committed by GitHub
parent e84f860c4f
commit 5772914840
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 325 additions and 155 deletions

View file

@ -7,6 +7,7 @@
- (Bugfix) Fix Networking Client
- (Feature) ConfigMap Inspector
- (Feature) Envoy Image Layer
- (Feature) Add ArangoDeployment ServerGroupType
## [1.2.42](https://github.com/arangodb/kube-arangodb/tree/1.2.42) (2024-07-23)
- (Maintenance) Go 1.22.4 & Kubernetes 1.29.6 libraries

View file

@ -122,6 +122,20 @@ var (
}
)
// Type returns the Group Type
func (g ServerGroup) Type() ServerGroupType {
switch g {
case ServerGroupAgents, ServerGroupSingle, ServerGroupDBServers, ServerGroupCoordinators:
return ServerGroupTypeArangoD
case ServerGroupImageDiscovery:
return ServerGroupTypeID
case ServerGroupSyncMasters, ServerGroupSyncWorkers:
return ServerGroupTypeArangoSync
default:
return ServerGroupTypeUnknown
}
}
// AsRole returns the "role" value for the given group.
func (g ServerGroup) AsRole() string {
switch g {

View file

@ -514,11 +514,12 @@ func (s ServerGroupSpec) Validate(group ServerGroup, used bool, mode DeploymentM
for _, arg := range s.Args {
parts := strings.Split(arg, "=")
optionKey := strings.TrimSpace(parts[0])
if group.IsArangod() {
switch group.Type() {
case ServerGroupTypeArangoD:
if arangodOptions.IsCriticalOption(optionKey) {
return errors.WithStack(errors.Wrapf(ValidationError, "Critical option '%s' cannot be overriden", optionKey))
}
} else if group.IsArangosync() {
case ServerGroupTypeArangoSync:
if arangosyncOptions.IsCriticalOption(optionKey) {
return errors.WithStack(errors.Wrapf(ValidationError, "Critical option '%s' cannot be overriden", optionKey))
}

View file

@ -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.
@ -61,3 +61,14 @@ func TestServerGroupIsArangosync(t *testing.T) {
assert.True(t, ServerGroupSyncMasters.IsArangosync())
assert.True(t, ServerGroupSyncWorkers.IsArangosync())
}
func TestServerGroupType(t *testing.T) {
assert.Equal(t, ServerGroupTypeUnknown, ServerGroupUnknown.Type())
assert.Equal(t, ServerGroupTypeID, ServerGroupImageDiscovery.Type())
assert.Equal(t, ServerGroupTypeArangoD, ServerGroupSingle.Type())
assert.Equal(t, ServerGroupTypeArangoD, ServerGroupAgents.Type())
assert.Equal(t, ServerGroupTypeArangoD, ServerGroupDBServers.Type())
assert.Equal(t, ServerGroupTypeArangoD, ServerGroupCoordinators.Type())
assert.Equal(t, ServerGroupTypeArangoSync, ServerGroupSyncMasters.Type())
assert.Equal(t, ServerGroupTypeArangoSync, ServerGroupSyncWorkers.Type())
}

View file

@ -0,0 +1,30 @@
//
// 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 v1
type ServerGroupType int
const (
ServerGroupTypeUnknown ServerGroupType = iota
ServerGroupTypeArangoD
ServerGroupTypeArangoSync
ServerGroupTypeID
)

View file

@ -122,6 +122,20 @@ var (
}
)
// Type returns the Group Type
func (g ServerGroup) Type() ServerGroupType {
switch g {
case ServerGroupAgents, ServerGroupSingle, ServerGroupDBServers, ServerGroupCoordinators:
return ServerGroupTypeArangoD
case ServerGroupImageDiscovery:
return ServerGroupTypeID
case ServerGroupSyncMasters, ServerGroupSyncWorkers:
return ServerGroupTypeArangoSync
default:
return ServerGroupTypeUnknown
}
}
// AsRole returns the "role" value for the given group.
func (g ServerGroup) AsRole() string {
switch g {

View file

@ -514,11 +514,12 @@ func (s ServerGroupSpec) Validate(group ServerGroup, used bool, mode DeploymentM
for _, arg := range s.Args {
parts := strings.Split(arg, "=")
optionKey := strings.TrimSpace(parts[0])
if group.IsArangod() {
switch group.Type() {
case ServerGroupTypeArangoD:
if arangodOptions.IsCriticalOption(optionKey) {
return errors.WithStack(errors.Wrapf(ValidationError, "Critical option '%s' cannot be overriden", optionKey))
}
} else if group.IsArangosync() {
case ServerGroupTypeArangoSync:
if arangosyncOptions.IsCriticalOption(optionKey) {
return errors.WithStack(errors.Wrapf(ValidationError, "Critical option '%s' cannot be overriden", optionKey))
}

View file

@ -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.
@ -61,3 +61,14 @@ func TestServerGroupIsArangosync(t *testing.T) {
assert.True(t, ServerGroupSyncMasters.IsArangosync())
assert.True(t, ServerGroupSyncWorkers.IsArangosync())
}
func TestServerGroupType(t *testing.T) {
assert.Equal(t, ServerGroupTypeUnknown, ServerGroupUnknown.Type())
assert.Equal(t, ServerGroupTypeID, ServerGroupImageDiscovery.Type())
assert.Equal(t, ServerGroupTypeArangoD, ServerGroupSingle.Type())
assert.Equal(t, ServerGroupTypeArangoD, ServerGroupAgents.Type())
assert.Equal(t, ServerGroupTypeArangoD, ServerGroupDBServers.Type())
assert.Equal(t, ServerGroupTypeArangoD, ServerGroupCoordinators.Type())
assert.Equal(t, ServerGroupTypeArangoSync, ServerGroupSyncMasters.Type())
assert.Equal(t, ServerGroupTypeArangoSync, ServerGroupSyncWorkers.Type())
}

View file

@ -0,0 +1,30 @@
//
// 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 v2alpha1
type ServerGroupType int
const (
ServerGroupTypeUnknown ServerGroupType = iota
ServerGroupTypeArangoD
ServerGroupTypeArangoSync
ServerGroupTypeID
)

View file

@ -107,12 +107,14 @@ func createTestTLSVolume(serverGroupString, ID string) core.Volume {
}
func createTestLifecycle(group api.ServerGroup) *core.Lifecycle {
if group.IsArangosync() {
switch group.Type() {
case api.ServerGroupTypeArangoSync:
lifecycle, _ := k8sutil.NewLifecycleFinalizers()
return lifecycle
default:
lifecycle, _ := k8sutil.NewLifecyclePort()
return lifecycle
}
lifecycle, _ := k8sutil.NewLifecyclePort()
return lifecycle
}
func createTestToken(deployment *Deployment, testCase *testCaseStruct, paths []string) (string, error) {
@ -864,52 +866,51 @@ func podDataSort() func(t *testing.T, p *core.Pod) {
func addLifecycle(name string, uuidRequired bool, license string, group api.ServerGroup) func(t *testing.T, p *core.Pod) {
return func(t *testing.T, p *core.Pod) {
if group.IsArangosync() {
return
}
if len(p.Spec.Containers) > 0 {
p.Spec.Containers[0].Env = append(k8sutil.GetLifecycleEnv(), p.Spec.Containers[0].Env...)
if license != "" {
p.Spec.Containers[0].Env = append([]core.EnvVar{
k8sutil.CreateEnvSecretKeySelector(constants.EnvArangoLicenseKey,
license, constants.SecretKeyToken)}, p.Spec.Containers[0].Env...)
}
}
if _, ok := k8sutil.GetAnyVolumeByName(p.Spec.Volumes, shared.LifecycleVolumeName); !ok {
p.Spec.Volumes = append([]core.Volume{k8sutil.LifecycleVolume()}, p.Spec.Volumes...)
}
if _, ok := k8sutil.GetAnyVolumeByName(p.Spec.Volumes, "arangod-data"); !ok {
p.Spec.Volumes = append([]core.Volume{k8sutil.LifecycleVolume()}, p.Spec.Volumes...)
}
if len(p.Spec.Containers) > 0 {
p.Spec.Containers[0].Lifecycle = createTestLifecycle(api.ServerGroupAgents)
}
if len(p.Spec.Containers) > 0 {
if _, ok := k8sutil.GetAnyVolumeMountByName(p.Spec.Containers[0].VolumeMounts, "lifecycle"); !ok {
p.Spec.Containers[0].VolumeMounts = append(p.Spec.Containers[0].VolumeMounts, k8sutil.LifecycleVolumeMount())
switch group.Type() {
case api.ServerGroupTypeArangoD:
if len(p.Spec.Containers) > 0 {
p.Spec.Containers[0].Env = append(k8sutil.GetLifecycleEnv(), p.Spec.Containers[0].Env...)
if license != "" {
p.Spec.Containers[0].Env = append([]core.EnvVar{
k8sutil.CreateEnvSecretKeySelector(constants.EnvArangoLicenseKey,
license, constants.SecretKeyToken)}, p.Spec.Containers[0].Env...)
}
}
if _, ok := kresources.GetAnyContainerByName(p.Spec.InitContainers, "init-lifecycle"); !ok {
if _, ok := k8sutil.GetAnyVolumeByName(p.Spec.Volumes, shared.LifecycleVolumeName); !ok {
p.Spec.Volumes = append([]core.Volume{k8sutil.LifecycleVolume()}, p.Spec.Volumes...)
}
if _, ok := k8sutil.GetAnyVolumeByName(p.Spec.Volumes, "arangod-data"); !ok {
p.Spec.Volumes = append([]core.Volume{k8sutil.LifecycleVolume()}, p.Spec.Volumes...)
}
if len(p.Spec.Containers) > 0 {
p.Spec.Containers[0].Lifecycle = createTestLifecycle(api.ServerGroupAgents)
}
if len(p.Spec.Containers) > 0 {
if _, ok := k8sutil.GetAnyVolumeMountByName(p.Spec.Containers[0].VolumeMounts, "lifecycle"); !ok {
p.Spec.Containers[0].VolumeMounts = append(p.Spec.Containers[0].VolumeMounts, k8sutil.LifecycleVolumeMount())
}
if _, ok := kresources.GetAnyContainerByName(p.Spec.InitContainers, "init-lifecycle"); !ok {
p.Spec.InitContainers = append(
[]core.Container{createTestLifecycleContainer(emptyResources)},
p.Spec.InitContainers...,
)
}
}
if _, ok := kresources.GetAnyContainerByName(p.Spec.InitContainers, "uuid"); !ok {
binaryPath, _ := os.Executable()
p.Spec.InitContainers = append(
[]core.Container{createTestLifecycleContainer(emptyResources)},
[]core.Container{
k8sutil.ArangodInitContainer("uuid", name, "rocksdb", binaryPath, testImageOperator, uuidRequired, securityContext.NewSecurityContext()),
},
p.Spec.InitContainers...,
)
}
}
if _, ok := kresources.GetAnyContainerByName(p.Spec.InitContainers, "uuid"); !ok {
binaryPath, _ := os.Executable()
p.Spec.InitContainers = append(
[]core.Container{
k8sutil.ArangodInitContainer("uuid", name, "rocksdb", binaryPath, testImageOperator, uuidRequired, securityContext.NewSecurityContext()),
},
p.Spec.InitContainers...,
)
}
}
}

View file

@ -34,6 +34,7 @@ import (
"github.com/arangodb/kube-arangodb/pkg/logging"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/arangodb/kube-arangodb/pkg/util/arangod"
"github.com/arangodb/kube-arangodb/pkg/util/assertion"
"github.com/arangodb/kube-arangodb/pkg/util/errors"
"github.com/arangodb/kube-arangodb/pkg/util/globals"
)
@ -123,13 +124,20 @@ func (s *stateInspector) RefreshState(ctx context.Context, members api.Deploymen
ctxChild, cancel := globals.GetGlobalTimeouts().ArangoDCheck().WithTimeout(ctx)
defer cancel()
if members[id].Group.IsArangosync() {
switch members[id].Group.Type() {
case api.ServerGroupTypeArangoSync:
results[id] = s.fetchArangosyncMemberState(ctxChild, members[id])
} else {
case api.ServerGroupTypeArangoD:
results[id] = s.fetchServerMemberState(ctxChild, members[id], servingGroup)
if results[id].IsServing() {
client = results[id].client
}
default:
assertion.InvalidGroupKey.Assert(true, "Unable to fetch Health for an unknown group: %s", members[id].Group.AsRole())
results[id] = State{
IsClusterHealthy: false,
serving: false,
}
}
})
@ -155,22 +163,26 @@ func (s *stateInspector) RefreshState(ctx context.Context, members api.Deploymen
continue
}
if members[i].Group.IsArangosync() {
// ArangoSync is considered as healthy when it is possible to fetch version.
results[i].IsClusterHealthy = true
continue
}
if v, ok := h.Members[driver.ServerID(m.Member.ID)]; ok {
results[i].IsClusterHealthy = v.Status == driver.ServerStatusGood
if results[i].IsServing() && v.SyncStatus == driver.ServerSyncStatusServing {
if cs.client == nil || util.Rand().Intn(100) > 50 {
// Set client from nil or take next client with 50% probability.
cs.client = results[i].client
cs.Version = results[i].Version
switch members[i].Group.Type() {
case api.ServerGroupTypeArangoD:
if v, ok := h.Members[driver.ServerID(m.Member.ID)]; ok {
results[i].IsClusterHealthy = v.Status == driver.ServerStatusGood
if results[i].IsServing() && v.SyncStatus == driver.ServerSyncStatusServing {
if cs.client == nil || util.Rand().Intn(100) > 50 {
// Set client from nil or take next client with 50% probability.
cs.client = results[i].client
cs.Version = results[i].Version
}
}
}
case api.ServerGroupTypeArangoSync:
// ArangoSync is considered as healthy when it is possible to fetch version.
results[i].IsClusterHealthy = true
default:
assertion.InvalidGroupKey.Assert(true, "Unable to fetch Health for an unknown group: %s", members[i].Group.AsRole())
results[i].IsClusterHealthy = false
}
}
return nil

View file

@ -25,6 +25,7 @@ import (
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
"github.com/arangodb/kube-arangodb/pkg/util/assertion"
"github.com/arangodb/kube-arangodb/pkg/util/errors"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/service"
@ -41,7 +42,8 @@ func GenerateMemberEndpoint(services service.Inspector, apiObject meta.Object, s
}
func GenerateMemberEndpointFromService(svc *core.Service, apiObject meta.Object, spec api.DeploymentSpec, group api.ServerGroup, member api.MemberStatus) (string, error) {
if group.IsArangod() {
switch group.Type() {
case api.ServerGroupTypeArangoD:
switch method := spec.CommunicationMethod.Get(); method {
case api.DeploymentCommunicationMethodDNS, api.DeploymentCommunicationMethodHeadlessDNS:
return k8sutil.CreateServiceDNSNameWithDomain(svc, spec.ClusterDomain), nil
@ -60,7 +62,9 @@ func GenerateMemberEndpointFromService(svc *core.Service, apiObject meta.Object,
default:
return k8sutil.CreatePodDNSNameWithDomain(apiObject, spec.ClusterDomain, group.AsRole(), member.ID), nil
}
} else {
case api.ServerGroupTypeArangoSync:
return k8sutil.CreateSyncMasterClientServiceDNSNameWithDomain(apiObject, spec.ClusterDomain), nil
default:
return "", assertion.InvalidGroupKey.Assert(true, "Unable to create Endpoint for an unknown group: %s", group.AsRole())
}
}

View file

@ -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.
@ -29,6 +29,7 @@ import (
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
"github.com/arangodb/kube-arangodb/pkg/deployment/client"
"github.com/arangodb/kube-arangodb/pkg/deployment/resources"
"github.com/arangodb/kube-arangodb/pkg/util/assertion"
"github.com/arangodb/kube-arangodb/pkg/util/errors"
"github.com/arangodb/kube-arangodb/pkg/util/globals"
)
@ -72,22 +73,27 @@ func (a *actionWaitForMemberUp) CheckProgress(ctx context.Context) (bool, bool,
ctxChild, cancel := globals.GetGlobalTimeouts().ArangoD().WithTimeout(ctx)
defer cancel()
if a.action.Group.IsArangosync() {
switch a.action.Group.Type() {
case api.ServerGroupTypeArangoD:
switch a.actionCtx.GetMode() {
case api.DeploymentModeSingle:
return a.checkProgressSingle(ctxChild)
case api.DeploymentModeActiveFailover:
if a.action.Group == api.ServerGroupAgents {
return a.checkProgressAgent()
}
return a.checkProgressSingleInActiveFailover(ctxChild)
default:
if a.action.Group == api.ServerGroupAgents {
return a.checkProgressAgent()
}
return a.checkProgressCluster(ctx)
}
case api.ServerGroupTypeArangoSync:
return a.checkProgressArangoSync(ctxChild)
}
switch a.actionCtx.GetMode() {
case api.DeploymentModeSingle:
return a.checkProgressSingle(ctxChild)
case api.DeploymentModeActiveFailover:
if a.action.Group == api.ServerGroupAgents {
return a.checkProgressAgent()
}
return a.checkProgressSingleInActiveFailover(ctxChild)
default:
if a.action.Group == api.ServerGroupAgents {
return a.checkProgressAgent()
}
return a.checkProgressCluster(ctx)
assertion.InvalidGroupKey.Assert(true, "Unable to execute action WaitForMemberUp for an unknown group: %s", a.action.Group.AsRole())
return true, false, nil
}
}

View file

@ -31,6 +31,7 @@ import (
"github.com/arangodb/kube-arangodb/pkg/deployment/client"
"github.com/arangodb/kube-arangodb/pkg/deployment/features"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/arangodb/kube-arangodb/pkg/util/assertion"
"github.com/arangodb/kube-arangodb/pkg/util/errors"
"github.com/arangodb/kube-arangodb/pkg/util/globals"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil/kerrors"
@ -157,7 +158,8 @@ func (s shutdownHelperAPI) Start(ctx context.Context) (bool, error) {
}
}
if group.IsArangod() {
switch group.Type() {
case api.ServerGroupTypeArangoD:
// Invoke shutdown endpoint
c, err := s.actionCtx.GetMembersState().GetMemberClient(s.action.MemberID)
if err != nil {
@ -177,14 +179,17 @@ func (s shutdownHelperAPI) Start(ctx context.Context) (bool, error) {
s.log.Err(err).Debug("Failed to shutdown member")
return false, errors.WithStack(err)
}
} else if group.IsArangosync() {
return false, nil
case api.ServerGroupTypeArangoSync:
// Terminate pod
if err := cache.Client().Kubernetes().CoreV1().Pods(cache.Namespace()).Delete(ctx, podName, meta.DeleteOptions{}); err != nil {
return false, errors.WithStack(err)
}
return false, nil
default:
assertion.InvalidGroupKey.Assert(true, "Unable to execute ShutdownAction for an unknown group: %s", group.AsRole())
return false, nil
}
return false, nil
}
// CheckProgress returns true when pod is terminated.

View file

@ -41,6 +41,7 @@ import (
"github.com/arangodb/kube-arangodb/pkg/deployment/features"
"github.com/arangodb/kube-arangodb/pkg/deployment/resources"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/arangodb/kube-arangodb/pkg/util/assertion"
"github.com/arangodb/kube-arangodb/pkg/util/constants"
"github.com/arangodb/kube-arangodb/pkg/util/crypto"
operatorHTTP "github.com/arangodb/kube-arangodb/pkg/util/http"
@ -542,10 +543,15 @@ func (r *Reconciler) keyfileRenewalRequired(ctx context.Context, apiObject k8sut
// Verify AltNames
var altNames memberTls.KeyfileInput
if group.IsArangosync() {
altNames, err = memberTls.GetSyncAltNames(apiObject, spec, tlsSpec, group, member)
} else {
switch group.Type() {
case api.ServerGroupTypeArangoD:
altNames, err = memberTls.GetServerAltNames(apiObject, spec, tlsSpec, service, group, member)
case api.ServerGroupTypeArangoSync:
altNames, err = memberTls.GetSyncAltNames(apiObject, spec, tlsSpec, group, member)
default:
assertion.InvalidGroupKey.Assert(true, "Unable to check TLS Key Renewal for an unknown group: %s", group.AsRole())
return false, false
}
if err != nil {
@ -568,37 +574,44 @@ func (r *Reconciler) keyfileRenewalRequired(ctx context.Context, apiObject k8sut
}
// Ensure secret is propagated only on 3.7.0+ enterprise and inplace mode
if mode == api.TLSRotateModeInPlace && group.IsArangod() {
conn, err := context.GetMembersState().GetMemberClient(member.ID)
if err != nil {
r.planLogger.Err(err).Warn("Unable to get client")
return false, false
}
if mode == api.TLSRotateModeInPlace {
switch group.Type() {
case api.ServerGroupTypeArangoD:
conn, err := context.GetMembersState().GetMemberClient(member.ID)
if err != nil {
r.planLogger.Err(err).Warn("Unable to get client")
return false, false
}
s, exists := cachedStatus.Secret().V1().GetSimple(k8sutil.CreateTLSKeyfileSecretName(apiObject.GetName(), group.AsRole(), member.ID))
if !exists {
r.planLogger.Warn("Keyfile secret is missing")
return false, false
}
s, exists := cachedStatus.Secret().V1().GetSimple(k8sutil.CreateTLSKeyfileSecretName(apiObject.GetName(), group.AsRole(), member.ID))
if !exists {
r.planLogger.Warn("Keyfile secret is missing")
return false, false
}
c := client.NewClient(conn.Connection(), r.log)
tls, err := c.GetTLS(ctx)
if err != nil {
r.planLogger.Err(err).Warn("Unable to get tls details")
return false, false
}
c := client.NewClient(conn.Connection(), r.log)
tls, err := c.GetTLS(ctx)
if err != nil {
r.planLogger.Err(err).Warn("Unable to get tls details")
return false, false
}
keyfile, ok := s.Data[constants.SecretTLSKeyfile]
if !ok {
r.planLogger.Warn("Keyfile secret is invalid")
return false, false
}
keyfile, ok := s.Data[constants.SecretTLSKeyfile]
if !ok {
r.planLogger.Warn("Keyfile secret is invalid")
return false, false
}
keyfileSha := util.SHA256(keyfile)
keyfileSha := util.SHA256(keyfile)
if tls.Result.KeyFile.GetSHA().Checksum() != keyfileSha {
r.planLogger.Str("current", tls.Result.KeyFile.GetSHA().Checksum()).Str("desired", keyfileSha).Debug("Unable to get tls details")
return true, false
if tls.Result.KeyFile.GetSHA().Checksum() != keyfileSha {
r.planLogger.Str("current", tls.Result.KeyFile.GetSHA().Checksum()).Str("desired", keyfileSha).Debug("Unable to get tls details")
return true, false
}
case api.ServerGroupTypeArangoSync:
break
default:
assertion.InvalidGroupKey.Assert(true, "Unable to check TLS Key Renewal for an unknown group: %s", group.AsRole())
}
}

View file

@ -42,6 +42,7 @@ import (
"github.com/arangodb/kube-arangodb/pkg/deployment/pod"
"github.com/arangodb/kube-arangodb/pkg/deployment/reconciler"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/arangodb/kube-arangodb/pkg/util/assertion"
"github.com/arangodb/kube-arangodb/pkg/util/constants"
"github.com/arangodb/kube-arangodb/pkg/util/errors"
"github.com/arangodb/kube-arangodb/pkg/util/globals"
@ -335,7 +336,8 @@ func (r *Resources) RenderPodForMember(ctx context.Context, acs sutil.ACS, spec
podName := k8sutil.CreatePodName(apiObject.GetName(), roleAbbr, m.ID, CreatePodSuffix(spec))
var podCreator interfaces.PodCreator
if group.IsArangod() {
switch group.Type() {
case api.ServerGroupTypeArangoD:
// Prepare arguments
autoUpgrade := m.Conditions.IsTrue(api.ConditionTypeAutoUpgrade) || spec.Upgrade.Get().AutoUpgrade
@ -353,7 +355,7 @@ func (r *Resources) RenderPodForMember(ctx context.Context, acs sutil.ACS, spec
arangoMember: *member,
cachedStatus: cache,
}
} else if group.IsArangosync() {
case api.ServerGroupTypeArangoSync:
// Check image
if !imageInfo.Enterprise {
log.Str("image", spec.GetImage()).Debug("Image is not an enterprise image")
@ -377,8 +379,8 @@ func (r *Resources) RenderPodForMember(ctx context.Context, acs sutil.ACS, spec
memberStatus: m,
cachedStatus: cache,
}
} else {
return nil, errors.Errorf("unable to render Pod")
default:
return nil, assertion.InvalidGroupKey.Assert(true, "Unable to render pod for an unknown group: %s", group.AsRole())
}
pod, err := RenderArangoPod(ctx, cache, apiObject, role, m.ID, podName, podCreator)
@ -468,7 +470,8 @@ func (r *Resources) createPodForMember(ctx context.Context, cachedStatus inspect
newPhase := api.MemberPhaseCreated
// Create pod
if group.IsArangod() {
switch group.Type() {
case api.ServerGroupTypeArangoD:
// Prepare arguments
autoUpgrade := m.Conditions.IsTrue(api.ConditionTypeAutoUpgrade)
if autoUpgrade {
@ -507,7 +510,7 @@ func (r *Resources) createPodForMember(ctx context.Context, cachedStatus inspect
} else {
log.Str("pod-name", pod.Name).Debug("Created pod with predefined image")
}
} else if group.IsArangosync() {
case api.ServerGroupTypeArangoSync:
// Check monitoring token secret
if group == api.ServerGroupSyncMasters {
// Create TLS secret
@ -545,6 +548,8 @@ func (r *Resources) createPodForMember(ctx context.Context, cachedStatus inspect
m.Pod.Propagate(&m)
log.Str("pod-name", pod.Name).Debug("Created pod")
default:
return assertion.InvalidGroupKey.Assert(true, "Unable to create pod for an unknown group: %s", group.AsRole())
}
member.GetPhaseExecutor().Execute(r.context.GetAPIObject(), spec, group, &m, api.Action{}, newPhase)

View file

@ -598,7 +598,7 @@ func (m *MemberArangoDPod) Annotations() map[string]string {
func (m *MemberArangoDPod) Labels() map[string]string {
l := collection.ReservedLabels().Filter(collection.MergeAnnotations(m.spec.Labels, m.groupSpec.Labels))
if m.group.IsArangod() && m.status.Topology != nil && m.deploymentStatus.Topology.Enabled() && m.deploymentStatus.Topology.ID == m.status.Topology.ID {
if m.status.Topology != nil && m.deploymentStatus.Topology.Enabled() && m.deploymentStatus.Topology.ID == m.status.Topology.ID {
if l == nil {
l = map[string]string{}
}

View file

@ -41,6 +41,7 @@ import (
"github.com/arangodb/kube-arangodb/pkg/deployment/pod"
"github.com/arangodb/kube-arangodb/pkg/metrics"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/arangodb/kube-arangodb/pkg/util/assertion"
"github.com/arangodb/kube-arangodb/pkg/util/constants"
"github.com/arangodb/kube-arangodb/pkg/util/errors"
"github.com/arangodb/kube-arangodb/pkg/util/globals"
@ -129,36 +130,41 @@ func (r *Resources) EnsureSecrets(ctx context.Context, cachedStatus inspectorInt
}
if err := reconcileRequired.ParallelAll(len(members), func(id int) error {
if !members[id].Group.IsArangod() {
switch members[id].Group.Type() {
case api.ServerGroupTypeArangoD:
memberName := members[id].Member.ArangoMemberName(r.context.GetAPIObject().GetName(), members[id].Group)
member, ok := cachedStatus.ArangoMember().V1().GetSimple(memberName)
if !ok {
return errors.Errorf("Member %s not found", memberName)
}
service, ok := cachedStatus.Service().V1().GetSimple(memberName)
if !ok {
return errors.Errorf("Service of member %s not found", memberName)
}
tlsKeyfileSecretName := k8sutil.AppendTLSKeyfileSecretPostfix(member.GetName())
if _, exists := cachedStatus.Secret().V1().GetSimple(tlsKeyfileSecretName); !exists {
serverNames, err := tls.GetServerAltNames(apiObject, spec, spec.TLS, service, members[id].Group, members[id].Member)
if err != nil {
return errors.WithStack(errors.Wrapf(err, "Failed to render alt names"))
}
owner := member.AsOwner()
if created, err := createTLSServerCertificate(ctx, log, cachedStatus, secrets, serverNames, spec.TLS, tlsKeyfileSecretName, &owner); err != nil && !kerrors.IsAlreadyExists(err) {
return errors.WithStack(errors.Wrapf(err, "Failed to create TLS keyfile secret"))
} else if created {
reconcileRequired.Required()
}
}
return nil
case api.ServerGroupTypeArangoSync:
// Nothing to do
return nil
default:
assertion.InvalidGroupKey.Assert(true, "Unable to create TLS Secret an unknown group: %s", members[id].Group.AsRole())
return nil
}
memberName := members[id].Member.ArangoMemberName(r.context.GetAPIObject().GetName(), members[id].Group)
member, ok := cachedStatus.ArangoMember().V1().GetSimple(memberName)
if !ok {
return errors.Errorf("Member %s not found", memberName)
}
service, ok := cachedStatus.Service().V1().GetSimple(memberName)
if !ok {
return errors.Errorf("Service of member %s not found", memberName)
}
tlsKeyfileSecretName := k8sutil.AppendTLSKeyfileSecretPostfix(member.GetName())
if _, exists := cachedStatus.Secret().V1().GetSimple(tlsKeyfileSecretName); !exists {
serverNames, err := tls.GetServerAltNames(apiObject, spec, spec.TLS, service, members[id].Group, members[id].Member)
if err != nil {
return errors.WithStack(errors.Wrapf(err, "Failed to render alt names"))
}
owner := member.AsOwner()
if created, err := createTLSServerCertificate(ctx, log, cachedStatus, secrets, serverNames, spec.TLS, tlsKeyfileSecretName, &owner); err != nil && !kerrors.IsAlreadyExists(err) {
return errors.WithStack(errors.Wrapf(err, "Failed to create TLS keyfile secret"))
} else if created {
reconcileRequired.Required()
}
}
return nil
}); err != nil {
return errors.Section(err, "TLS TrustStore")
}

View file

@ -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.
@ -22,6 +22,8 @@ package assertion
import (
"fmt"
"github.com/arangodb/kube-arangodb/pkg/util/errors"
)
type Key string
@ -30,19 +32,20 @@ const (
KeyUnknown Key = ""
DeprecatedActionKey Key = "DeprecatedAction"
CommunityLicenseCheckKey Key = "CommunityLicenseCheck"
InvalidGroupKey Key = "InvalidGroup"
)
func (k Key) Assert(condition bool, msg string, args ...interface{}) {
assert(2, condition, k, msg, args...)
func (k Key) Assert(condition bool, msg string, args ...interface{}) error {
return assert(2, condition, k, msg, args...)
}
func Assert(condition bool, key Key, msg string, args ...interface{}) {
assert(2, condition, key, msg, args...)
func Assert(condition bool, key Key, msg string, args ...interface{}) error {
return assert(2, condition, key, msg, args...)
}
func assert(skip int, condition bool, key Key, msg string, args ...interface{}) {
func assert(skip int, condition bool, key Key, msg string, args ...interface{}) error {
if !condition {
return
return nil
}
metricsObject.incKeyMetric(key)
@ -50,4 +53,6 @@ func assert(skip int, condition bool, key Key, msg string, args ...interface{})
frames := frames(skip)
_assert(frames, fmt.Sprintf(msg, args...))
return errors.WithStack(errors.Errorf("Error Assertion `%s`: %s", key, fmt.Sprintf(msg, args...)))
}