From 0ca5a9ec67014b993c5bc8852e0029c412671799 Mon Sep 17 00:00:00 2001 From: ajanikow <12255597+ajanikow@users.noreply.github.com> Date: Thu, 1 Jul 2021 11:30:02 +0000 Subject: [PATCH 1/2] Use persistent name and namespace --- CHANGELOG.md | 1 + .../deployment/v2alpha1/deployment_spec.go | 43 +++++++++++++++++++ pkg/apis/deployment/v2alpha1/server_group.go | 10 +++++ .../v2alpha1/zz_generated.deepcopy.go | 5 +++ pkg/deployment/context_impl.go | 33 +++++++------- pkg/deployment/deployment.go | 5 +++ pkg/deployment/deployment_inspector.go | 4 +- pkg/deployment/resources/context.go | 2 + 8 files changed, 84 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8349daed4..e1cdecad9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Change Log ## [master](https://github.com/arangodb/kube-arangodb/tree/master) (N/A) +- Use persistent name and namespace in ArangoDeployment reconcilation loop ## [1.1.9](https://github.com/arangodb/kube-arangodb/tree/1.1.9) (2021-05-28) - Add IP, DNS, ShortDNS, HeadlessService (Default) communication methods diff --git a/pkg/apis/deployment/v2alpha1/deployment_spec.go b/pkg/apis/deployment/v2alpha1/deployment_spec.go index 8ac93cbb6..17b0d94a0 100644 --- a/pkg/apis/deployment/v2alpha1/deployment_spec.go +++ b/pkg/apis/deployment/v2alpha1/deployment_spec.go @@ -50,6 +50,46 @@ func validatePullPolicy(v core.PullPolicy) error { } } +// DeploymentCommunicationMethod define communication method used for inter-cluster communication +type DeploymentCommunicationMethod string + +// Get returns communication method from pointer. If pointer is nil default is returned. +func (d *DeploymentCommunicationMethod) Get() DeploymentCommunicationMethod { + if d == nil { + return DefaultDeploymentCommunicationMethod + } + + switch v := *d; v { + case DeploymentCommunicationMethodHeadlessService, DeploymentCommunicationMethodDNS, DeploymentCommunicationMethodIP, DeploymentCommunicationMethodShortDNS: + return v + default: + return DefaultDeploymentCommunicationMethod + } +} + +// String returns string representation of method. +func (d DeploymentCommunicationMethod) String() string { + return string(d) +} + +// New returns pointer. +func (d DeploymentCommunicationMethod) New() *DeploymentCommunicationMethod { + return &d +} + +const ( + // DefaultDeploymentCommunicationMethod define default communication method. + DefaultDeploymentCommunicationMethod = DeploymentCommunicationMethodHeadlessService + // DeploymentCommunicationMethodHeadlessService define old communication mechanism, based on headless service. + DeploymentCommunicationMethodHeadlessService DeploymentCommunicationMethod = "headless" + // DeploymentCommunicationMethodDNS define ClusterIP Service DNS based communication. + DeploymentCommunicationMethodDNS DeploymentCommunicationMethod = "dns" + // DeploymentCommunicationMethodDNS define ClusterIP Service DNS based communication. Use namespaced short DNS (used in migration) + DeploymentCommunicationMethodShortDNS DeploymentCommunicationMethod = "short-dns" + // DeploymentCommunicationMethodIP define ClusterIP Servce IP based communication. + DeploymentCommunicationMethodIP DeploymentCommunicationMethod = "ip" +) + // DeploymentSpec contains the spec part of a ArangoDeployment resource. type DeploymentSpec struct { Mode *DeploymentMode `json:"mode,omitempty"` @@ -118,6 +158,9 @@ type DeploymentSpec struct { Timeouts *Timeouts `json:"timeouts,omitempty"` ClusterDomain *string `json:"ClusterDomain,omitempty"` + + // CommunicationMethod define communication method used in deployment + CommunicationMethod *DeploymentCommunicationMethod `json:"communicationMethod,omitempty"` } // GetRestoreFrom returns the restore from string or empty string if not set diff --git a/pkg/apis/deployment/v2alpha1/server_group.go b/pkg/apis/deployment/v2alpha1/server_group.go index 97e5d0d39..fd1487570 100644 --- a/pkg/apis/deployment/v2alpha1/server_group.go +++ b/pkg/apis/deployment/v2alpha1/server_group.go @@ -35,6 +35,16 @@ func (g *ServerGroup) UnmarshalJSON(bytes []byte) error { return nil } + { + // Try with int + var s int + + if err := json.Unmarshal(bytes, &s); err == nil { + *g = ServerGroupFromRole(ServerGroup(s).AsRole()) + return nil + } + } + var s string if err := json.Unmarshal(bytes, &s); err != nil { diff --git a/pkg/apis/deployment/v2alpha1/zz_generated.deepcopy.go b/pkg/apis/deployment/v2alpha1/zz_generated.deepcopy.go index db1520552..cd4a1ed21 100644 --- a/pkg/apis/deployment/v2alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/deployment/v2alpha1/zz_generated.deepcopy.go @@ -567,6 +567,11 @@ func (in *DeploymentSpec) DeepCopyInto(out *DeploymentSpec) { *out = new(string) **out = **in } + if in.CommunicationMethod != nil { + in, out := &in.CommunicationMethod, &out.CommunicationMethod + *out = new(DeploymentCommunicationMethod) + **out = **in + } return } diff --git a/pkg/deployment/context_impl.go b/pkg/deployment/context_impl.go index 867a68d83..5d6514624 100644 --- a/pkg/deployment/context_impl.go +++ b/pkg/deployment/context_impl.go @@ -114,10 +114,10 @@ func (d *Deployment) GetOperatorUUIDImage() string { return d.config.OperatorUUIDInitImage } -// GetNamespSecretsInterfaceace returns the kubernetes namespace that contains +// GetNamespace returns the kubernetes namespace that contains // this deployment. func (d *Deployment) GetNamespace() string { - return d.apiObject.GetNamespace() + return d.namespace } // GetPhase returns the current phase of the deployment @@ -275,7 +275,7 @@ func (d *Deployment) getAuth() (driver.Authentication, error) { return nil, nil } - var secrets secret.ReadInterface = d.GetKubeCli().CoreV1().Secrets(d.apiObject.GetNamespace()) + var secrets secret.ReadInterface = d.GetKubeCli().CoreV1().Secrets(d.GetNamespace()) if currentState := d.currentState; currentState != nil { secrets = currentState.SecretReadInterface() } @@ -294,7 +294,7 @@ func (d *Deployment) getAuth() (driver.Authentication, error) { secret = string(jwt) } else { - s, err := secrets.Get(context.Background(), pod.JWTSecretFolder(d.apiObject.GetName()), meta.GetOptions{}) + s, err := secrets.Get(context.Background(), pod.JWTSecretFolder(d.GetName()), meta.GetOptions{}) if err != nil { d.deps.Log.Error().Err(err).Msgf("Unable to get secret") return nil, errors.Newf("JWT Folder Secret is missing") @@ -327,7 +327,7 @@ func (d *Deployment) GetSyncServerClient(ctx context.Context, group api.ServerGr // Fetch monitoring token log := d.deps.Log kubecli := d.deps.KubeCli - ns := d.apiObject.GetNamespace() + ns := d.GetNamespace() secrets := kubecli.CoreV1().Secrets(ns) secretName := d.apiObject.Spec.Sync.Monitoring.GetTokenSecretName() monitoringToken, err := k8sutil.GetTokenSecret(ctx, secrets, secretName) @@ -392,7 +392,7 @@ func (d *Deployment) GetPod(ctx context.Context, podName string) (*v1.Pod, error // of the deployment. If the pod does not exist, the error is ignored. func (d *Deployment) DeletePod(ctx context.Context, podName string) error { log := d.deps.Log - ns := d.apiObject.GetNamespace() + ns := d.GetNamespace() err := k8sutil.RunWithTimeout(ctx, func(ctxChild context.Context) error { return d.deps.KubeCli.CoreV1().Pods(ns).Delete(ctxChild, podName, meta.DeleteOptions{}) }) @@ -449,7 +449,7 @@ func (d *Deployment) RemovePodFinalizers(ctx context.Context, podName string) er // of the deployment. If the pvc does not exist, the error is ignored. func (d *Deployment) DeletePvc(ctx context.Context, pvcName string) error { log := d.deps.Log - ns := d.apiObject.GetNamespace() + ns := d.GetNamespace() err := k8sutil.RunWithTimeout(ctx, func(ctxChild context.Context) error { return d.deps.KubeCli.CoreV1().PersistentVolumeClaims(ns).Delete(ctxChild, pvcName, meta.DeleteOptions{}) }) @@ -482,7 +482,7 @@ func (d *Deployment) UpdatePvc(ctx context.Context, pvc *v1.PersistentVolumeClai func (d *Deployment) GetOwnedPVCs() ([]v1.PersistentVolumeClaim, error) { // Get all current PVCs log := d.deps.Log - pvcs, err := d.deps.KubeCli.CoreV1().PersistentVolumeClaims(d.apiObject.GetNamespace()).List(context.Background(), k8sutil.DeploymentListOpt(d.apiObject.GetName())) + pvcs, err := d.deps.KubeCli.CoreV1().PersistentVolumeClaims(d.GetNamespace()).List(context.Background(), k8sutil.DeploymentListOpt(d.GetName())) if err != nil { log.Debug().Err(err).Msg("Failed to list PVCs") return nil, errors.WithStack(err) @@ -501,7 +501,7 @@ func (d *Deployment) GetPvc(ctx context.Context, pvcName string) (*v1.Persistent ctxChild, cancel := context.WithTimeout(ctx, k8sutil.GetRequestTimeout()) defer cancel() - pvc, err := d.deps.KubeCli.CoreV1().PersistentVolumeClaims(d.apiObject.GetNamespace()).Get(ctxChild, pvcName, meta.GetOptions{}) + pvc, err := d.deps.KubeCli.CoreV1().PersistentVolumeClaims(d.GetNamespace()).Get(ctxChild, pvcName, meta.GetOptions{}) if err != nil { log.Debug().Err(err).Str("pvc-name", pvcName).Msg("Failed to get PVC") return nil, errors.WithStack(err) @@ -512,9 +512,8 @@ func (d *Deployment) GetPvc(ctx context.Context, pvcName string) (*v1.Persistent // GetTLSKeyfile returns the keyfile encoded TLS certificate+key for // the given member. func (d *Deployment) GetTLSKeyfile(group api.ServerGroup, member api.MemberStatus) (string, error) { - secretName := k8sutil.CreateTLSKeyfileSecretName(d.apiObject.GetName(), group.AsRole(), member.ID) - ns := d.apiObject.GetNamespace() - secrets := d.deps.KubeCli.CoreV1().Secrets(ns) + secretName := k8sutil.CreateTLSKeyfileSecretName(d.GetName(), group.AsRole(), member.ID) + secrets := d.deps.KubeCli.CoreV1().Secrets(d.GetNamespace()) result, err := k8sutil.GetTLSKeyfileSecret(secrets, secretName) if err != nil { return "", errors.WithStack(err) @@ -525,8 +524,8 @@ func (d *Deployment) GetTLSKeyfile(group api.ServerGroup, member api.MemberStatu // DeleteTLSKeyfile removes the Secret containing the TLS keyfile for the given member. // If the secret does not exist, the error is ignored. func (d *Deployment) DeleteTLSKeyfile(ctx context.Context, group api.ServerGroup, member api.MemberStatus) error { - secretName := k8sutil.CreateTLSKeyfileSecretName(d.apiObject.GetName(), group.AsRole(), member.ID) - ns := d.apiObject.GetNamespace() + secretName := k8sutil.CreateTLSKeyfileSecretName(d.GetName(), group.AsRole(), member.ID) + ns := d.GetNamespace() err := k8sutil.RunWithTimeout(ctx, func(ctxChild context.Context) error { return d.deps.KubeCli.CoreV1().Secrets(ns).Delete(ctxChild, secretName, meta.DeleteOptions{}) }) @@ -539,7 +538,7 @@ func (d *Deployment) DeleteTLSKeyfile(ctx context.Context, group api.ServerGroup // DeleteSecret removes the Secret with given name. // If the secret does not exist, the error is ignored. func (d *Deployment) DeleteSecret(secretName string) error { - ns := d.apiObject.GetNamespace() + ns := d.GetNamespace() if err := d.deps.KubeCli.CoreV1().Secrets(ns).Delete(context.Background(), secretName, meta.DeleteOptions{}); err != nil && !k8sutil.IsNotFound(err) { return errors.WithStack(err) } @@ -614,14 +613,14 @@ func (d *Deployment) SecretsInterface() k8sutil.SecretInterface { } func (d *Deployment) GetName() string { - return d.apiObject.GetName() + return d.name } func (d *Deployment) GetOwnedPods(ctx context.Context) ([]v1.Pod, error) { ctxChild, cancel := context.WithTimeout(ctx, k8sutil.GetRequestTimeout()) defer cancel() - pods, err := d.GetKubeCli().CoreV1().Pods(d.apiObject.GetNamespace()).List(ctxChild, meta.ListOptions{}) + pods, err := d.GetKubeCli().CoreV1().Pods(d.GetNamespace()).List(ctxChild, meta.ListOptions{}) if err != nil { return nil, err } diff --git a/pkg/deployment/deployment.go b/pkg/deployment/deployment.go index a0a3b5b2f..84883699f 100644 --- a/pkg/deployment/deployment.go +++ b/pkg/deployment/deployment.go @@ -107,6 +107,9 @@ const ( // Deployment is the in process state of an ArangoDeployment. type Deployment struct { + name string + namespace string + apiObject *api.ArangoDeployment // API object status struct { mutex sync.Mutex @@ -143,6 +146,8 @@ func New(config Config, deps Dependencies, apiObject *api.ArangoDeployment) (*De d := &Deployment{ apiObject: apiObject, + name: apiObject.GetName(), + namespace: apiObject.GetNamespace(), config: config, deps: deps, eventCh: make(chan *deploymentEvent, deploymentEventQueueSize), diff --git a/pkg/deployment/deployment_inspector.go b/pkg/deployment/deployment_inspector.go index decc8857d..ffd550013 100644 --- a/pkg/deployment/deployment_inspector.go +++ b/pkg/deployment/deployment_inspector.go @@ -99,7 +99,7 @@ func (d *Deployment) inspectDeployment(lastInterval util.Interval) util.Interval nextInterval := lastInterval hasError := false - deploymentName := d.apiObject.GetName() + deploymentName := d.GetName() defer metrics.SetDuration(inspectDeploymentDurationGauges.WithLabelValues(deploymentName), start) cachedStatus, err := inspector.NewInspector(d.GetKubeCli(), d.GetMonitoringV1Cli(), d.GetArangoCli(), d.GetNamespace()) @@ -112,7 +112,7 @@ func (d *Deployment) inspectDeployment(lastInterval util.Interval) util.Interval var updated *api.ArangoDeployment err = k8sutil.RunWithTimeout(ctxReconciliation, func(ctxChild context.Context) error { var err error - updated, err = d.deps.DatabaseCRCli.DatabaseV1().ArangoDeployments(d.apiObject.GetNamespace()).Get(ctxChild, deploymentName, metav1.GetOptions{}) + updated, err = d.deps.DatabaseCRCli.DatabaseV1().ArangoDeployments(d.GetNamespace()).Get(ctxChild, deploymentName, metav1.GetOptions{}) return err }) if k8sutil.IsNotFound(err) { diff --git a/pkg/deployment/resources/context.go b/pkg/deployment/resources/context.go index 2f4ad19aa..50b1b5404 100644 --- a/pkg/deployment/resources/context.go +++ b/pkg/deployment/resources/context.go @@ -81,6 +81,8 @@ type Context interface { GetMetricsExporterImage() string // GetArangoImage returns the image name containing the default arango image GetArangoImage() string + // GetName returns the name of the deployment + GetName() string // GetNamespace returns the namespace that contains the deployment GetNamespace() string // CreateEvent creates a given event. From 5df28dd5ecbe57bb95d4ff22817ed4d9fb0c1584 Mon Sep 17 00:00:00 2001 From: ajanikow <12255597+ajanikow@users.noreply.github.com> Date: Thu, 1 Jul 2021 14:20:56 +0000 Subject: [PATCH 2/2] Fix IT --- pkg/deployment/deployment_suite_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/deployment/deployment_suite_test.go b/pkg/deployment/deployment_suite_test.go index 8df3a5dbc..7ded8b599 100644 --- a/pkg/deployment/deployment_suite_test.go +++ b/pkg/deployment/deployment_suite_test.go @@ -465,6 +465,8 @@ func createTestDeployment(config Config, arangoDeployment *api.ArangoDeployment) d := &Deployment{ apiObject: arangoDeployment, + name: arangoDeployment.GetName(), + namespace: arangoDeployment.GetNamespace(), config: config, deps: deps, eventCh: make(chan *deploymentEvent, deploymentEventQueueSize),