Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
43 changes: 43 additions & 0 deletions pkg/apis/deployment/v2alpha1/deployment_spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions pkg/apis/deployment/v2alpha1/server_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
5 changes: 5 additions & 0 deletions pkg/apis/deployment/v2alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 16 additions & 17 deletions pkg/deployment/context_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
}
Expand All @@ -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")
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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{})
})
Expand Down Expand Up @@ -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{})
})
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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{})
})
Expand All @@ -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)
}
Expand Down Expand Up @@ -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
}
Expand Down
5 changes: 5 additions & 0 deletions pkg/deployment/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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),
Expand Down
4 changes: 2 additions & 2 deletions pkg/deployment/deployment_inspector.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand All @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions pkg/deployment/deployment_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
2 changes: 2 additions & 0 deletions pkg/deployment/resources/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down