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

FEATURE/Remove v1alpha from core API (#527)

This commit is contained in:
Adam Janikowski 2020-03-03 10:34:54 +01:00 committed by GitHub
parent e7d5d8f3a9
commit 3254e2f789
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
99 changed files with 44 additions and 9263 deletions

View file

@ -1,6 +1,8 @@
# Change Log
## [master](https://github.com/arangodb/kube-arangodb/tree/master) (N/A)
- Removal of v1alpha support for ArangoDeployment, ArangoDeploymentReplication, ArangoBackup
- Added new command to operator - version
## [0.4.5](https://github.com/arangodb/kube-arangodb/tree/0.4.5) (2020-03-02)
- Add Customizable SecurityContext for ArangoDeployment pods

View file

@ -196,7 +196,7 @@ update-generated:
"all" \
"github.com/arangodb/kube-arangodb/pkg/generated" \
"github.com/arangodb/kube-arangodb/pkg/apis" \
"deployment:v1alpha deployment:v1 replication:v1alpha replication:v1 storage:v1alpha backup:v1alpha backup:v1" \
"deployment:v1 replication:v1 storage:v1alpha backup:v1" \
--go-header-file "./tools/codegen/boilerplate.go.txt" \
$(VERIFYARGS)

1
go.mod
View file

@ -8,6 +8,7 @@ replace (
k8s.io/api => k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.0.0-20190409022649-727a075fdec8
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d
k8s.io/client-go => k8s.io/client-go v11.0.0+incompatible
k8s.io/code-generator => ./deps/k8s.io/code-generator
)

5
go.sum
View file

@ -323,6 +323,7 @@ github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc h1:f8eY6cV/x1x+HLjOp4r72s/31/V2aTUtg5oKRRPf8/Q=
github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
@ -814,8 +815,10 @@ k8s.io/apiextensions-apiserver v0.0.0-20190409022649-727a075fdec8/go.mod h1:Ixke
k8s.io/apiextensions-apiserver v0.0.0-20190503111720-ae1f9335ecc1 h1:k73F2NiQUzHW8P1WO1vUbbP5CuHv0X5Hvg46gd7NeKE=
k8s.io/apiextensions-apiserver v0.0.0-20190503111720-ae1f9335ecc1/go.mod h1:CKD5Qnu6XIncLe210SKvQDnIWeLYyL152baFY0+81hU=
k8s.io/apimachinery v0.0.0-20180904193909-def12e63c512/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
k8s.io/apimachinery v0.0.0-20181127025237-2b1284ed4c93/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
k8s.io/apimachinery v0.0.0-20190221213512-86fb29eff628 h1:UYfHH+KEF88OTg+GojQUwFTNxbxwmoktLwutUzR0GPg=
k8s.io/apimachinery v0.0.0-20190221213512-86fb29eff628/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
k8s.io/apimachinery v0.0.0-20190313205120-d7deff9243b1/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d h1:Jmdtdt1ZnoGfWWIIik61Z7nKYgO3J+swQJtPYsP9wHA=
k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
k8s.io/apimachinery v0.0.0-20190424052434-11f1676e3da4/go.mod h1:5CBnzrKYGHzv9ZsSKmQ8wHt4XI4/TUBPDwYM9FlZMyw=
@ -830,6 +833,8 @@ k8s.io/client-go v0.0.0-20190425172711-65184652c889/go.mod h1:PeVFCnjeDy6EwLN+wd
k8s.io/client-go v2.0.0-alpha.0.0.20180910083459-2cefa64ff137+incompatible h1:Ch3wIkSY4QNrqRAJqgQIIpwqaCi7bbiIP23BAV9Qq/U=
k8s.io/client-go v2.0.0-alpha.0.0.20180910083459-2cefa64ff137+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
k8s.io/client-go v2.0.0-alpha.0.0.20181121191925-a47917edff34+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
k8s.io/client-go v10.0.0+incompatible h1:F1IqCqw7oMBzDkqlcBymRq1450wD0eNqLE9jzUrIi34=
k8s.io/client-go v10.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
k8s.io/client-go v11.0.0+incompatible h1:LBbX2+lOwY9flffWlJM7f1Ct8V2SRNiMRDFeiwnJo9o=
k8s.io/client-go v11.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
k8s.io/code-generator v0.0.0-20180621065459-6702109cc68e h1:lD3gN/b2A3KiZIAG/EPHkC/BIrA9NdFbSXmx90Ej+jU=

View file

@ -1,60 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Adam Janikowski
//
package v1alpha
import (
"github.com/arangodb/kube-arangodb/pkg/apis/backup"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
const (
FinalizerArangoBackup = backup.ArangoBackupCRDName + "/cleanup"
)
var (
FinalizersArangoBackup = []string{
FinalizerArangoBackup,
}
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ArangoBackupList is a list of ArangoDB backups.
type ArangoBackupList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ArangoBackup `json:"items"`
}
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ArangoBackup contains definition and status of the ArangoDB Backup.
type ArangoBackup struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec ArangoBackupSpec `json:"spec"`
Status ArangoBackupStatus `json:"status"`
}

View file

@ -1,82 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Adam Janikowski
//
package v1alpha
import (
"fmt"
deployment "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
"github.com/arangodb/kube-arangodb/pkg/backup/utils"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ArangoBackupPolicyList is a list of ArangoDB backup policy.
type ArangoBackupPolicyList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ArangoBackupPolicy `json:"items"`
}
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ArangoBackupPolicy contains definition and status of the ArangoDB Backup Policy.
type ArangoBackupPolicy struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec ArangoBackupPolicySpec `json:"spec"`
Status ArangoBackupPolicyStatus `json:"status"`
}
func (a *ArangoBackupPolicy) NewBackup(d *deployment.ArangoDeployment) *ArangoBackup {
policyName := a.Name
spec := &ArangoBackupSpec{
Deployment: ArangoBackupSpecDeployment{
Name: d.Name,
},
Upload: a.Spec.BackupTemplate.Upload.DeepCopy(),
Options: a.Spec.BackupTemplate.Options.DeepCopy(),
PolicyName: &policyName,
}
return &ArangoBackup{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-%s", d.Name, utils.RandomString(8)),
Namespace: a.Namespace,
Labels: d.Labels,
Annotations: d.Annotations,
Finalizers: []string{
FinalizerArangoBackup,
},
},
Spec: *spec,
}
}

View file

@ -1,41 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Adam Janikowski
//
package v1alpha
import (
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type ArangoBackupPolicySpec struct {
Schedule string `json:"schedule"`
DeploymentSelector *meta.LabelSelector `json:"selector,omitempty"`
BackupTemplate ArangoBackupTemplate `json:"template"`
}
type ArangoBackupTemplate struct {
Options *ArangoBackupSpecOptions `json:"options,omitempty"`
Upload *ArangoBackupSpecOperation `json:"upload,omitempty"`
}

View file

@ -1,48 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Adam Janikowski
//
package v1alpha
import (
"fmt"
"time"
"github.com/robfig/cron"
)
func (a *ArangoBackupPolicy) Validate() error {
if err := a.Spec.Validate(); err != nil {
return err
}
return nil
}
func (a *ArangoBackupPolicySpec) Validate() error {
if expr, err := cron.ParseStandard(a.Schedule); err != nil {
return fmt.Errorf("error while parsing expr: %s", err.Error())
} else if expr.Next(time.Now()).IsZero() {
return fmt.Errorf("invalid schedule format")
}
return nil
}

View file

@ -1,58 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Adam Janikowski
//
package v1alpha
type ArangoBackupSpec struct {
// Deployment
Deployment ArangoBackupSpecDeployment `json:"deployment,omitempty"`
Options *ArangoBackupSpecOptions `json:"options,omitempty"`
// Download
Download *ArangoBackupSpecDownload `json:"download,omitempty"`
// Upload
Upload *ArangoBackupSpecOperation `json:"upload,omitempty"`
PolicyName *string `json:"policyName,omitempty"`
}
type ArangoBackupSpecDeployment struct {
Name string `json:"name,omitempty"`
}
type ArangoBackupSpecOptions struct {
Timeout *float32 `json:"timeout,omitempty"`
AllowInconsistent *bool `json:"allowInconsistent,omitempty"`
}
type ArangoBackupSpecOperation struct {
RepositoryURL string `json:"repositoryURL"`
CredentialsSecretName string `json:"credentialsSecretName,omitempty"`
}
type ArangoBackupSpecDownload struct {
ArangoBackupSpecOperation `json:",inline"`
ID string `json:"id"`
}

View file

@ -1,108 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Adam Janikowski
//
package v1alpha
import (
"github.com/arangodb/kube-arangodb/pkg/backup/state"
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
)
const (
ArangoBackupStateNone state.State = ""
ArangoBackupStatePending state.State = "Pending"
ArangoBackupStateScheduled state.State = "Scheduled"
ArangoBackupStateDownload state.State = "Download"
ArangoBackupStateDownloadError state.State = "DownloadError"
ArangoBackupStateDownloading state.State = "Downloading"
ArangoBackupStateCreate state.State = "Create"
ArangoBackupStateUpload state.State = "Upload"
ArangoBackupStateUploading state.State = "Uploading"
ArangoBackupStateUploadError state.State = "UploadError"
ArangoBackupStateReady state.State = "Ready"
ArangoBackupStateDeleted state.State = "Deleted"
ArangoBackupStateFailed state.State = "Failed"
ArangoBackupStateUnavailable state.State = "Unavailable"
)
var ArangoBackupStateMap = state.Map{
ArangoBackupStateNone: {ArangoBackupStatePending},
ArangoBackupStatePending: {ArangoBackupStateScheduled, ArangoBackupStateFailed},
ArangoBackupStateScheduled: {ArangoBackupStateDownload, ArangoBackupStateCreate, ArangoBackupStateFailed},
ArangoBackupStateDownload: {ArangoBackupStateDownloading, ArangoBackupStateFailed, ArangoBackupStateDownloadError},
ArangoBackupStateDownloading: {ArangoBackupStateReady, ArangoBackupStateFailed, ArangoBackupStateDownloadError},
ArangoBackupStateDownloadError: {ArangoBackupStatePending, ArangoBackupStateFailed},
ArangoBackupStateCreate: {ArangoBackupStateReady, ArangoBackupStateFailed},
ArangoBackupStateUpload: {ArangoBackupStateUploading, ArangoBackupStateFailed, ArangoBackupStateDeleted, ArangoBackupStateUploadError},
ArangoBackupStateUploading: {ArangoBackupStateReady, ArangoBackupStateFailed, ArangoBackupStateUploadError},
ArangoBackupStateUploadError: {ArangoBackupStateFailed, ArangoBackupStateReady},
ArangoBackupStateReady: {ArangoBackupStateDeleted, ArangoBackupStateFailed, ArangoBackupStateUpload, ArangoBackupStateUnavailable},
ArangoBackupStateDeleted: {ArangoBackupStateFailed, ArangoBackupStateReady},
ArangoBackupStateFailed: {ArangoBackupStatePending},
ArangoBackupStateUnavailable: {ArangoBackupStateReady, ArangoBackupStateDeleted, ArangoBackupStateFailed},
}
type ArangoBackupState struct {
// State holds the current high level state of the backup
State state.State `json:"state"`
Time meta.Time `json:"time"`
// Message for the state this object is in.
Message string `json:"message,omitempty"`
// Progress for the operation
Progress *ArangoBackupProgress `json:"progress,omitempty"`
}
func (a *ArangoBackupState) Equal(b *ArangoBackupState) bool {
if a == b {
return true
}
if a == nil && b != nil || a != nil && b == nil {
return false
}
return a.State == b.State &&
a.Time.Equal(&b.Time) &&
a.Message == b.Message &&
a.Progress.Equal(b.Progress)
}
type ArangoBackupProgress struct {
JobID string `json:"jobID"`
Progress string `json:"progress"`
}
func (a *ArangoBackupProgress) Equal(b *ArangoBackupProgress) bool {
if a == b {
return true
}
if a == nil && b != nil || a != nil && b == nil {
return false
}
return a.JobID == b.JobID &&
a.Progress == b.Progress
}

View file

@ -1,97 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Adam Janikowski
//
package v1alpha
import (
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// ArangoBackupStatus contains the status part of
// an ArangoBackup.
type ArangoBackupStatus struct {
ArangoBackupState `json:",inline"`
Backup *ArangoBackupDetails `json:"backup,omitempty"`
Available bool `json:"available"`
}
func (a *ArangoBackupStatus) Equal(b *ArangoBackupStatus) bool {
if a == b {
return true
}
if a == nil && b != nil || a != nil && b == nil {
return false
}
return a.ArangoBackupState.Equal(&b.ArangoBackupState) &&
a.Backup.Equal(b.Backup) &&
a.Available == b.Available
}
type ArangoBackupDetails struct {
ID string `json:"id"`
Version string `json:"version"`
PotentiallyInconsistent *bool `json:"potentiallyInconsistent,omitempty"`
SizeInBytes uint64 `json:"sizeInBytes,omitempty"`
NumberOfDBServers uint `json:"numberOfDBServers,omitempty"`
Uploaded *bool `json:"uploaded,omitempty"`
Downloaded *bool `json:"downloaded,omitempty"`
Imported *bool `json:"imported,omitempty"`
CreationTimestamp meta.Time `json:"createdAt"`
}
func (a *ArangoBackupDetails) Equal(b *ArangoBackupDetails) bool {
if a == b {
return true
}
if a == nil && b != nil || a != nil && b == nil {
return false
}
return a.ID == b.ID &&
a.Version == b.Version &&
a.SizeInBytes == b.SizeInBytes &&
a.NumberOfDBServers == b.NumberOfDBServers &&
a.CreationTimestamp.Equal(&b.CreationTimestamp) &&
compareBoolPointer(a.PotentiallyInconsistent, b.PotentiallyInconsistent) &&
compareBoolPointer(a.Uploaded, b.Uploaded) &&
compareBoolPointer(a.Downloaded, b.Downloaded) &&
compareBoolPointer(a.Imported, b.Imported)
}
func compareBoolPointer(a, b * bool) bool {
if a == nil && b != nil || a != nil && b == nil {
return false
}
if a == b {
return true
}
if *a == *b {
return true
}
return false
}

View file

@ -1,81 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Adam Janikowski
//
package v1alpha
import "fmt"
func (a *ArangoBackup) Validate() error {
if err := a.Spec.Validate(); err != nil {
return err
}
if err := a.Status.Validate(); err != nil {
return err
}
return nil
}
func (a *ArangoBackupSpec) Validate() error {
if a.Deployment.Name == "" {
return fmt.Errorf("deployment name can not be empty")
}
if a.Download != nil {
if err := a.Download.Validate(); err != nil {
return err
}
}
if a.Upload != nil {
if err := a.Upload.Validate(); err != nil {
return err
}
}
return nil
}
func (a *ArangoBackupSpecOperation) Validate() error {
if a.RepositoryURL == "" {
return fmt.Errorf("RepositoryURL can not be empty")
}
return nil
}
func (a *ArangoBackupSpecDownload) Validate() error {
if a.ID == "" {
return fmt.Errorf("ID can not be empty")
}
return a.ArangoBackupSpecOperation.Validate()
}
func (a *ArangoBackupStatus) Validate() error {
if err := ArangoBackupStateMap.Exists(a.ArangoBackupState.State); err != nil {
return err
}
return nil
}

View file

@ -1,25 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Adam Janikowski
//
// +k8s:deepcopy-gen=package
// +groupName=backup.arangodb.com
package v1alpha

View file

@ -1,58 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Adam Janikowski
//
package v1alpha
import (
"github.com/arangodb/kube-arangodb/pkg/apis/backup"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
const (
ArangoBackupVersion = "v1alpha"
)
var (
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
AddToScheme = SchemeBuilder.AddToScheme
SchemeGroupVersion = schema.GroupVersion{Group: backup.ArangoBackupGroupName, Version: ArangoBackupVersion}
)
// Resource gets an ArangoCluster GroupResource for a specified resource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
// addKnownTypes adds the set of types defined in this package to the supplied scheme.
func addKnownTypes(s *runtime.Scheme) error {
s.AddKnownTypes(SchemeGroupVersion,
&ArangoBackup{},
&ArangoBackupList{},
&ArangoBackupPolicy{},
&ArangoBackupPolicyList{},
)
metav1.AddToGroupVersion(s, SchemeGroupVersion)
return nil
}

View file

@ -1,426 +0,0 @@
// +build !ignore_autogenerated
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1alpha
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoBackup) DeepCopyInto(out *ArangoBackup) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoBackup.
func (in *ArangoBackup) DeepCopy() *ArangoBackup {
if in == nil {
return nil
}
out := new(ArangoBackup)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ArangoBackup) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoBackupDetails) DeepCopyInto(out *ArangoBackupDetails) {
*out = *in
if in.PotentiallyInconsistent != nil {
in, out := &in.PotentiallyInconsistent, &out.PotentiallyInconsistent
*out = new(bool)
**out = **in
}
if in.Uploaded != nil {
in, out := &in.Uploaded, &out.Uploaded
*out = new(bool)
**out = **in
}
if in.Downloaded != nil {
in, out := &in.Downloaded, &out.Downloaded
*out = new(bool)
**out = **in
}
if in.Imported != nil {
in, out := &in.Imported, &out.Imported
*out = new(bool)
**out = **in
}
in.CreationTimestamp.DeepCopyInto(&out.CreationTimestamp)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoBackupDetails.
func (in *ArangoBackupDetails) DeepCopy() *ArangoBackupDetails {
if in == nil {
return nil
}
out := new(ArangoBackupDetails)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoBackupList) DeepCopyInto(out *ArangoBackupList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]ArangoBackup, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoBackupList.
func (in *ArangoBackupList) DeepCopy() *ArangoBackupList {
if in == nil {
return nil
}
out := new(ArangoBackupList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ArangoBackupList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoBackupPolicy) DeepCopyInto(out *ArangoBackupPolicy) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoBackupPolicy.
func (in *ArangoBackupPolicy) DeepCopy() *ArangoBackupPolicy {
if in == nil {
return nil
}
out := new(ArangoBackupPolicy)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ArangoBackupPolicy) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoBackupPolicyList) DeepCopyInto(out *ArangoBackupPolicyList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]ArangoBackupPolicy, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoBackupPolicyList.
func (in *ArangoBackupPolicyList) DeepCopy() *ArangoBackupPolicyList {
if in == nil {
return nil
}
out := new(ArangoBackupPolicyList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ArangoBackupPolicyList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoBackupPolicySpec) DeepCopyInto(out *ArangoBackupPolicySpec) {
*out = *in
if in.DeploymentSelector != nil {
in, out := &in.DeploymentSelector, &out.DeploymentSelector
*out = new(v1.LabelSelector)
(*in).DeepCopyInto(*out)
}
in.BackupTemplate.DeepCopyInto(&out.BackupTemplate)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoBackupPolicySpec.
func (in *ArangoBackupPolicySpec) DeepCopy() *ArangoBackupPolicySpec {
if in == nil {
return nil
}
out := new(ArangoBackupPolicySpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoBackupPolicyStatus) DeepCopyInto(out *ArangoBackupPolicyStatus) {
*out = *in
in.Scheduled.DeepCopyInto(&out.Scheduled)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoBackupPolicyStatus.
func (in *ArangoBackupPolicyStatus) DeepCopy() *ArangoBackupPolicyStatus {
if in == nil {
return nil
}
out := new(ArangoBackupPolicyStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoBackupProgress) DeepCopyInto(out *ArangoBackupProgress) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoBackupProgress.
func (in *ArangoBackupProgress) DeepCopy() *ArangoBackupProgress {
if in == nil {
return nil
}
out := new(ArangoBackupProgress)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoBackupSpec) DeepCopyInto(out *ArangoBackupSpec) {
*out = *in
out.Deployment = in.Deployment
if in.Options != nil {
in, out := &in.Options, &out.Options
*out = new(ArangoBackupSpecOptions)
(*in).DeepCopyInto(*out)
}
if in.Download != nil {
in, out := &in.Download, &out.Download
*out = new(ArangoBackupSpecDownload)
**out = **in
}
if in.Upload != nil {
in, out := &in.Upload, &out.Upload
*out = new(ArangoBackupSpecOperation)
**out = **in
}
if in.PolicyName != nil {
in, out := &in.PolicyName, &out.PolicyName
*out = new(string)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoBackupSpec.
func (in *ArangoBackupSpec) DeepCopy() *ArangoBackupSpec {
if in == nil {
return nil
}
out := new(ArangoBackupSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoBackupSpecDeployment) DeepCopyInto(out *ArangoBackupSpecDeployment) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoBackupSpecDeployment.
func (in *ArangoBackupSpecDeployment) DeepCopy() *ArangoBackupSpecDeployment {
if in == nil {
return nil
}
out := new(ArangoBackupSpecDeployment)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoBackupSpecDownload) DeepCopyInto(out *ArangoBackupSpecDownload) {
*out = *in
out.ArangoBackupSpecOperation = in.ArangoBackupSpecOperation
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoBackupSpecDownload.
func (in *ArangoBackupSpecDownload) DeepCopy() *ArangoBackupSpecDownload {
if in == nil {
return nil
}
out := new(ArangoBackupSpecDownload)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoBackupSpecOperation) DeepCopyInto(out *ArangoBackupSpecOperation) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoBackupSpecOperation.
func (in *ArangoBackupSpecOperation) DeepCopy() *ArangoBackupSpecOperation {
if in == nil {
return nil
}
out := new(ArangoBackupSpecOperation)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoBackupSpecOptions) DeepCopyInto(out *ArangoBackupSpecOptions) {
*out = *in
if in.Timeout != nil {
in, out := &in.Timeout, &out.Timeout
*out = new(float32)
**out = **in
}
if in.AllowInconsistent != nil {
in, out := &in.AllowInconsistent, &out.AllowInconsistent
*out = new(bool)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoBackupSpecOptions.
func (in *ArangoBackupSpecOptions) DeepCopy() *ArangoBackupSpecOptions {
if in == nil {
return nil
}
out := new(ArangoBackupSpecOptions)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoBackupState) DeepCopyInto(out *ArangoBackupState) {
*out = *in
in.Time.DeepCopyInto(&out.Time)
if in.Progress != nil {
in, out := &in.Progress, &out.Progress
*out = new(ArangoBackupProgress)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoBackupState.
func (in *ArangoBackupState) DeepCopy() *ArangoBackupState {
if in == nil {
return nil
}
out := new(ArangoBackupState)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoBackupStatus) DeepCopyInto(out *ArangoBackupStatus) {
*out = *in
in.ArangoBackupState.DeepCopyInto(&out.ArangoBackupState)
if in.Backup != nil {
in, out := &in.Backup, &out.Backup
*out = new(ArangoBackupDetails)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoBackupStatus.
func (in *ArangoBackupStatus) DeepCopy() *ArangoBackupStatus {
if in == nil {
return nil
}
out := new(ArangoBackupStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoBackupTemplate) DeepCopyInto(out *ArangoBackupTemplate) {
*out = *in
if in.Options != nil {
in, out := &in.Options, &out.Options
*out = new(ArangoBackupSpecOptions)
(*in).DeepCopyInto(*out)
}
if in.Upload != nil {
in, out := &in.Upload, &out.Upload
*out = new(ArangoBackupSpecOperation)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoBackupTemplate.
func (in *ArangoBackupTemplate) DeepCopy() *ArangoBackupTemplate {
if in == nil {
return nil
}
out := new(ArangoBackupTemplate)
in.DeepCopyInto(out)
return out
}

View file

@ -76,7 +76,7 @@ type ServerGroupSpec struct {
type ServerGroupSpecSecurityContext struct {
// DropAllCapabilities specifies if capabilities should be dropped for this pod containers
//
// Deprecated: This field is added for backward compatibility. Will be removed in 1.0.0.
// Deprecated: This field is added for backward compatibility. Will be removed in 1.1.0.
DropAllCapabilities *bool `json:"dropAllCapabilities,omitempty"`
// AddCapabilities add new capabilities to containers
AddCapabilities []v1.Capability `json:"addCapabilities,omitempty"`
@ -84,7 +84,7 @@ type ServerGroupSpecSecurityContext struct {
// GetDropAllCapabilities returns flag if capabilities should be dropped
//
// Deprecated: This function is added for backward compatibility. Will be removed in 1.0.0.
// Deprecated: This function is added for backward compatibility. Will be removed in 1.1.0.
func (s *ServerGroupSpecSecurityContext) GetDropAllCapabilities() bool {
if s == nil {
return true

View file

@ -1,93 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"github.com/pkg/errors"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
)
// AuthenticationSpec holds authentication specific configuration settings
type AuthenticationSpec struct {
JWTSecretName *string `json:"jwtSecretName,omitempty"`
}
const (
// JWTSecretNameDisabled is the value of JWTSecretName to use for disabling authentication.
JWTSecretNameDisabled = "None"
)
// GetJWTSecretName returns the value of jwtSecretName.
func (s AuthenticationSpec) GetJWTSecretName() string {
return util.StringOrDefault(s.JWTSecretName)
}
// IsAuthenticated returns true if authentication is enabled.
// Returns false other (when JWTSecretName == "None").
func (s AuthenticationSpec) IsAuthenticated() bool {
return s.GetJWTSecretName() != JWTSecretNameDisabled
}
// Validate the given spec
func (s AuthenticationSpec) Validate(required bool) error {
if required && !s.IsAuthenticated() {
return maskAny(errors.Wrap(ValidationError, "JWT secret is required"))
}
if s.IsAuthenticated() {
if err := k8sutil.ValidateResourceName(s.GetJWTSecretName()); err != nil {
return maskAny(err)
}
}
return nil
}
// SetDefaults fills in missing defaults
func (s *AuthenticationSpec) SetDefaults(defaultJWTSecretName string) {
if s.GetJWTSecretName() == "" {
// Note that we don't check for nil here, since even a specified, but empty
// string should result in the default value.
s.JWTSecretName = util.NewString(defaultJWTSecretName)
}
}
// SetDefaultsFrom fills unspecified fields with a value from given source spec.
func (s *AuthenticationSpec) SetDefaultsFrom(source AuthenticationSpec) {
if s.JWTSecretName == nil {
s.JWTSecretName = util.NewStringOrNil(source.JWTSecretName)
}
}
// ResetImmutableFields replaces all immutable fields in the given target with values from the source spec.
// It returns a list of fields that have been reset.
// Field names are relative to given field prefix.
func (s AuthenticationSpec) ResetImmutableFields(fieldPrefix string, target *AuthenticationSpec) []string {
var resetFields []string
if s.IsAuthenticated() != target.IsAuthenticated() {
// Note: You can change the name, but not from empty to non-empty (or reverse).
target.JWTSecretName = util.NewStringOrNil(s.JWTSecretName)
resetFields = append(resetFields, fieldPrefix+".jwtSecretName")
}
return resetFields
}

View file

@ -1,105 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"testing"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/stretchr/testify/assert"
)
func TestAuthenticationSpecValidate(t *testing.T) {
// Valid
assert.Nil(t, AuthenticationSpec{JWTSecretName: util.NewString("None")}.Validate(false))
assert.Nil(t, AuthenticationSpec{JWTSecretName: util.NewString("foo")}.Validate(false))
assert.Nil(t, AuthenticationSpec{JWTSecretName: util.NewString("foo")}.Validate(true))
// Not valid
assert.Error(t, AuthenticationSpec{JWTSecretName: util.NewString("Foo")}.Validate(false))
}
func TestAuthenticationSpecIsAuthenticated(t *testing.T) {
assert.False(t, AuthenticationSpec{JWTSecretName: util.NewString("None")}.IsAuthenticated())
assert.True(t, AuthenticationSpec{JWTSecretName: util.NewString("foo")}.IsAuthenticated())
assert.True(t, AuthenticationSpec{JWTSecretName: util.NewString("")}.IsAuthenticated())
}
func TestAuthenticationSpecSetDefaults(t *testing.T) {
def := func(spec AuthenticationSpec) AuthenticationSpec {
spec.SetDefaults("test-jwt")
return spec
}
assert.Equal(t, "test-jwt", def(AuthenticationSpec{}).GetJWTSecretName())
assert.Equal(t, "foo", def(AuthenticationSpec{JWTSecretName: util.NewString("foo")}).GetJWTSecretName())
}
func TestAuthenticationSpecResetImmutableFields(t *testing.T) {
tests := []struct {
Original AuthenticationSpec
Target AuthenticationSpec
Expected AuthenticationSpec
Result []string
}{
// Valid "changes"
{
AuthenticationSpec{JWTSecretName: util.NewString("None")},
AuthenticationSpec{JWTSecretName: util.NewString("None")},
AuthenticationSpec{JWTSecretName: util.NewString("None")},
nil,
},
{
AuthenticationSpec{JWTSecretName: util.NewString("foo")},
AuthenticationSpec{JWTSecretName: util.NewString("foo")},
AuthenticationSpec{JWTSecretName: util.NewString("foo")},
nil,
},
{
AuthenticationSpec{JWTSecretName: util.NewString("foo")},
AuthenticationSpec{JWTSecretName: util.NewString("foo2")},
AuthenticationSpec{JWTSecretName: util.NewString("foo2")},
nil,
},
// Invalid changes
{
AuthenticationSpec{JWTSecretName: util.NewString("foo")},
AuthenticationSpec{JWTSecretName: util.NewString("None")},
AuthenticationSpec{JWTSecretName: util.NewString("foo")},
[]string{"test.jwtSecretName"},
},
{
AuthenticationSpec{JWTSecretName: util.NewString("None")},
AuthenticationSpec{JWTSecretName: util.NewString("foo")},
AuthenticationSpec{JWTSecretName: util.NewString("None")},
[]string{"test.jwtSecretName"},
},
}
for _, test := range tests {
result := test.Original.ResetImmutableFields("test", &test.Target)
assert.Equal(t, test.Result, result)
assert.Equal(t, test.Expected, test.Target)
}
}

View file

@ -1,136 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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 v1alpha
import (
"fmt"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
)
const (
// UserNameRoot root user name
UserNameRoot = "root"
)
// PasswordSecretName contains user password secret name
type PasswordSecretName string
const (
// PasswordSecretNameNone is magic value for no action
PasswordSecretNameNone PasswordSecretName = "None"
// PasswordSecretNameAuto is magic value for autogenerate name
PasswordSecretNameAuto PasswordSecretName = "Auto"
)
// PasswordSecretNameList is a map from username to secretnames
type PasswordSecretNameList map[string]PasswordSecretName
// BootstrapSpec contains information for cluster bootstrapping
type BootstrapSpec struct {
// PasswordSecretNames contains a map of username to password-secret-name
PasswordSecretNames PasswordSecretNameList `json:"passwordSecretNames,omitempty"`
}
// IsNone returns true if p is None or p is empty
func (p PasswordSecretName) IsNone() bool {
return p == PasswordSecretNameNone || p == ""
}
// IsAuto returns true if p is Auto
func (p PasswordSecretName) IsAuto() bool {
return p == PasswordSecretNameAuto
}
// GetSecretName returns the secret name given by the specs. Or None if not set.
func (s PasswordSecretNameList) GetSecretName(user string) PasswordSecretName {
if s != nil {
if secretname, ok := s[user]; ok {
return secretname
}
}
return PasswordSecretNameNone
}
// getSecretNameForUserPassword returns the default secret name for the given user
func getSecretNameForUserPassword(deploymentname, username string) PasswordSecretName {
return PasswordSecretName(k8sutil.FixupResourceName(deploymentname + "-" + username + "-password"))
}
// Validate the specification.
func (b *BootstrapSpec) Validate() error {
for username, secretname := range b.PasswordSecretNames {
// Remove this restriction as soon as we can bootstrap databases
if username != UserNameRoot {
return fmt.Errorf("only username `root` allowed in passwordSecretNames")
}
if secretname.IsNone() {
if username != UserNameRoot {
return fmt.Errorf("magic value None not allowed for %s", username)
}
} else {
if err := k8sutil.ValidateResourceName(string(secretname)); err != nil {
return maskAny(err)
}
}
}
return nil
}
// SetDefaults fills in default values when a field is not specified.
func (b *BootstrapSpec) SetDefaults(deploymentname string) {
if b.PasswordSecretNames == nil {
b.PasswordSecretNames = make(map[string]PasswordSecretName)
}
// If root is not set init with Auto
if _, ok := b.PasswordSecretNames[UserNameRoot]; !ok {
b.PasswordSecretNames[UserNameRoot] = PasswordSecretNameNone
}
// Replace Auto with generated secret name
for user, secretname := range b.PasswordSecretNames {
if secretname.IsAuto() {
b.PasswordSecretNames[user] = getSecretNameForUserPassword(deploymentname, user)
}
}
}
// NewPasswordSecretNameListOrNil returns nil if input is nil, otherwise returns a clone of the given value.
func NewPasswordSecretNameListOrNil(list PasswordSecretNameList) PasswordSecretNameList {
if list == nil {
return nil
}
var newList = make(PasswordSecretNameList)
for k, v := range list {
newList[k] = v
}
return newList
}
// SetDefaultsFrom fills unspecified fields with a value from given source spec.
func (b *BootstrapSpec) SetDefaultsFrom(source BootstrapSpec) {
if b.PasswordSecretNames == nil {
b.PasswordSecretNames = NewPasswordSecretNameListOrNil(source.PasswordSecretNames)
}
}

View file

@ -1,91 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
time "time"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/pkg/errors"
)
// ChaosSpec holds configuration for the deployment chaos monkey.
type ChaosSpec struct {
// Enabled switches the chaos monkey for a deployment on or off.
Enabled *bool `json:"enabled,omitempty"`
// Interval is the time between events
Interval *time.Duration `json:"interval,omitempty"`
// KillPodProbability is the chance of a pod being killed during an event
KillPodProbability *Percent `json:"kill-pod-probability,omitempty"`
}
// IsEnabled returns the value of enabled.
func (s ChaosSpec) IsEnabled() bool {
return util.BoolOrDefault(s.Enabled)
}
// GetInterval returns the value of interval.
func (s ChaosSpec) GetInterval() time.Duration {
return util.DurationOrDefault(s.Interval)
}
// GetKillPodProbability returns the value of kill-pod-probability.
func (s ChaosSpec) GetKillPodProbability() Percent {
return PercentOrDefault(s.KillPodProbability)
}
// Validate the given spec
func (s ChaosSpec) Validate() error {
if s.IsEnabled() {
if s.GetInterval() <= 0 {
return maskAny(errors.Wrapf(ValidationError, "Interval must be > 0"))
}
if err := s.GetKillPodProbability().Validate(); err != nil {
return maskAny(err)
}
}
return nil
}
// SetDefaults fills in missing defaults
func (s *ChaosSpec) SetDefaults() {
if s.GetInterval() == 0 {
s.Interval = util.NewDuration(time.Minute)
}
if s.GetKillPodProbability() == 0 {
s.KillPodProbability = NewPercent(50)
}
}
// SetDefaultsFrom fills unspecified fields with a value from given source spec.
func (s *ChaosSpec) SetDefaultsFrom(source ChaosSpec) {
if s.Enabled == nil {
s.Enabled = util.NewBoolOrNil(source.Enabled)
}
if s.Interval == nil {
s.Interval = util.NewDurationOrNil(source.Interval)
}
if s.KillPodProbability == nil {
s.KillPodProbability = NewPercentOrNil(source.KillPodProbability)
}
}

View file

@ -1,187 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"github.com/arangodb/kube-arangodb/pkg/util"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// ConditionType is a strongly typed condition name
type ConditionType string
const (
// ConditionTypeReady indicates that the member or entire deployment is ready and running normally.
ConditionTypeReady ConditionType = "Ready"
// ConditionTypeTerminated indicates that the member has terminated and will not restart.
ConditionTypeTerminated ConditionType = "Terminated"
// ConditionTypeAutoUpgrade indicates that the member has to be started with `--database.auto-upgrade` once.
ConditionTypeAutoUpgrade ConditionType = "AutoUpgrade"
// ConditionTypeCleanedOut indicates that the member (dbserver) has been cleaned out.
// Always check in combination with ConditionTypeTerminated.
ConditionTypeCleanedOut ConditionType = "CleanedOut"
// ConditionTypeAgentRecoveryNeeded indicates that the member (agent) will no
// longer recover from its current volume and there has to be rebuild
// using the recovery procedure.
ConditionTypeAgentRecoveryNeeded ConditionType = "AgentRecoveryNeeded"
// ConditionTypePodSchedulingFailure indicates that one or more pods belonging to the deployment cannot be schedule.
ConditionTypePodSchedulingFailure ConditionType = "PodSchedulingFailure"
// ConditionTypeSecretsChanged indicates that the value of one of more secrets used by
// the deployment have changed. Once that is the case, the operator will no longer
// touch the deployment, until the original secrets have been restored.
ConditionTypeSecretsChanged ConditionType = "SecretsChanged"
// ConditionTypeMemberOfCluster indicates that the member is a known member of the ArangoDB cluster.
ConditionTypeMemberOfCluster ConditionType = "MemberOfCluster"
// ConditionTypeBootstrapCompleted indicates that the initial cluster bootstrap has been completed.
ConditionTypeBootstrapCompleted ConditionType = "BootstrapCompleted"
// ConditionTypeBootstrapSucceded indicates that the initial cluster bootstrap completed successfully.
ConditionTypeBootstrapSucceded ConditionType = "BootstrapSucceded"
// ConditionTypeTerminating indicates that the member is terminating but not yet terminated.
ConditionTypeTerminating ConditionType = "Terminating"
)
// Condition represents one current condition of a deployment or deployment member.
// A condition might not show up if it is not happening.
// For example, if a cluster is not upgrading, the Upgrading condition would not show up.
type Condition struct {
// Type of condition.
Type ConditionType `json:"type"`
// Status of the condition, one of True, False, Unknown.
Status v1.ConditionStatus `json:"status"`
// The last time this condition was updated.
LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"`
// Last time the condition transitioned from one status to another.
LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
// The reason for the condition's last transition.
Reason string `json:"reason,omitempty"`
// A human readable message indicating details about the transition.
Message string `json:"message,omitempty"`
}
// ConditionList is a list of conditions.
// Each type is allowed only once.
type ConditionList []Condition
// Equal checks for equality
func (list ConditionList) Equal(other ConditionList) bool {
if len(list) != len(other) {
return false
}
for i := 0; i < len(list); i++ {
c, found := other.Get(list[i].Type)
if !found {
return false
}
if !list[i].Equal(c) {
return false
}
}
return true
}
// Equal checks for equality
func (c Condition) Equal(other Condition) bool {
return c.Type == other.Type &&
c.Status == other.Status &&
util.TimeCompareEqual(c.LastUpdateTime, other.LastUpdateTime) &&
util.TimeCompareEqual(c.LastTransitionTime, other.LastTransitionTime) &&
c.Reason == other.Reason &&
c.Message == other.Message
}
// IsTrue return true when a condition with given type exists and its status is `True`.
func (list ConditionList) IsTrue(conditionType ConditionType) bool {
c, found := list.Get(conditionType)
return found && c.Status == v1.ConditionTrue
}
// Get a condition by type.
// Returns true if found, false if not found.
func (list ConditionList) Get(conditionType ConditionType) (Condition, bool) {
for _, x := range list {
if x.Type == conditionType {
return x, true
}
}
// Not found
return Condition{}, false
}
// Update the condition, replacing an old condition with same type (if any)
// Returns true when changes were made, false otherwise.
func (list *ConditionList) Update(conditionType ConditionType, status bool, reason, message string) bool {
src := *list
statusX := v1.ConditionFalse
if status {
statusX = v1.ConditionTrue
}
for i, x := range src {
if x.Type == conditionType {
if x.Status != statusX {
// Transition to another status
src[i].Status = statusX
now := metav1.Now()
src[i].LastTransitionTime = now
src[i].LastUpdateTime = now
src[i].Reason = reason
src[i].Message = message
} else if x.Reason != reason || x.Message != message {
src[i].LastUpdateTime = metav1.Now()
src[i].Reason = reason
src[i].Message = message
} else {
return false
}
return true
}
}
// Not found
now := metav1.Now()
*list = append(src, Condition{
Type: conditionType,
LastUpdateTime: now,
LastTransitionTime: now,
Status: statusX,
Reason: reason,
Message: message,
})
return true
}
// Remove the condition with given type.
// Returns true if removed, or false if not found.
func (list *ConditionList) Remove(conditionType ConditionType) bool {
src := *list
for i, x := range src {
if x.Type == conditionType {
*list = append(src[:i], src[i+1:]...)
return true
}
}
// Not found
return false
}

View file

@ -1,99 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestConditionListIsTrue(t *testing.T) {
assert.False(t, ConditionList{}.IsTrue(ConditionTypeReady))
cl := ConditionList{}
cl.Update(ConditionTypeReady, true, "test", "msg")
assert.True(t, cl.IsTrue(ConditionTypeReady))
assert.False(t, cl.IsTrue(ConditionTypeTerminated))
cl.Update(ConditionTypeReady, false, "test", "msg")
assert.False(t, cl.IsTrue(ConditionTypeReady))
cl.Remove(ConditionTypeReady)
assert.False(t, cl.IsTrue(ConditionTypeReady))
assert.Equal(t, 0, len(cl))
}
func TestConditionListGet(t *testing.T) {
conv := func(c Condition, b bool) []interface{} {
return []interface{}{c, b}
}
cl := ConditionList{}
assert.EqualValues(t, conv(Condition{}, false), conv(cl.Get(ConditionTypeReady)))
cl.Update(ConditionTypeReady, false, "test", "msg")
assert.EqualValues(t, conv(cl[0], true), conv(cl.Get(ConditionTypeReady)))
}
func TestConditionListUpdate(t *testing.T) {
cl := ConditionList{}
assert.Equal(t, 0, len(cl))
assert.True(t, cl.Update(ConditionTypeReady, true, "test", "msg"))
assert.True(t, cl.IsTrue(ConditionTypeReady))
assert.Equal(t, 1, len(cl))
assert.False(t, cl.Update(ConditionTypeReady, true, "test", "msg"))
assert.True(t, cl.IsTrue(ConditionTypeReady))
assert.Equal(t, 1, len(cl))
assert.True(t, cl.Update(ConditionTypeReady, false, "test", "msg"))
assert.False(t, cl.IsTrue(ConditionTypeReady))
assert.Equal(t, 1, len(cl))
assert.True(t, cl.Update(ConditionTypeReady, false, "test2", "msg"))
assert.False(t, cl.IsTrue(ConditionTypeReady))
assert.Equal(t, 1, len(cl))
assert.True(t, cl.Update(ConditionTypeReady, false, "test2", "msg2"))
assert.False(t, cl.IsTrue(ConditionTypeReady))
assert.Equal(t, 1, len(cl))
}
func TestConditionListRemove(t *testing.T) {
cl := ConditionList{}
assert.Equal(t, 0, len(cl))
cl.Update(ConditionTypeReady, true, "test", "msg")
cl.Update(ConditionTypeTerminated, false, "test", "msg")
assert.Equal(t, 2, len(cl))
assert.True(t, cl.Remove(ConditionTypeReady))
assert.Equal(t, 1, len(cl))
assert.False(t, cl.Remove(ConditionTypeReady))
assert.Equal(t, 1, len(cl))
assert.True(t, cl.Remove(ConditionTypeTerminated))
assert.Equal(t, 0, len(cl))
}

View file

@ -1,95 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"github.com/arangodb/kube-arangodb/pkg/apis/deployment"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ArangoDeploymentList is a list of ArangoDB clusters.
type ArangoDeploymentList struct {
metav1.TypeMeta `json:",inline"`
// Standard list metadata
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
metav1.ListMeta `json:"metadata,omitempty"`
Items []ArangoDeployment `json:"items"`
}
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ArangoDeployment contains the entire Kubernetes info for an ArangoDB database deployment.
type ArangoDeployment struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec DeploymentSpec `json:"spec"`
Status DeploymentStatus `json:"status"`
}
type ServerGroupFunc func(ServerGroup, ServerGroupSpec, *MemberStatusList) error
// AsOwner creates an OwnerReference for the given deployment
func (d *ArangoDeployment) AsOwner() metav1.OwnerReference {
trueVar := true
return metav1.OwnerReference{
APIVersion: SchemeGroupVersion.String(),
Kind: deployment.ArangoDeploymentResourceKind,
Name: d.Name,
UID: d.UID,
Controller: &trueVar,
// For now BlockOwnerDeletion does not work on OpenShift, so we leave it out.
//BlockOwnerDeletion: &trueVar,
}
}
// ForeachServerGroup calls the given callback for all server groups.
// If the callback returns an error, this error is returned and no other server
// groups are processed.
// Groups are processed in this order: agents, single, dbservers, coordinators, syncmasters, syncworkers
func (d *ArangoDeployment) ForeachServerGroup(cb ServerGroupFunc, status *DeploymentStatus) error {
if status == nil {
status = &d.Status
}
if err := cb(ServerGroupAgents, d.Spec.Agents, &status.Members.Agents); err != nil {
return maskAny(err)
}
if err := cb(ServerGroupSingle, d.Spec.Single, &status.Members.Single); err != nil {
return maskAny(err)
}
if err := cb(ServerGroupDBServers, d.Spec.DBServers, &status.Members.DBServers); err != nil {
return maskAny(err)
}
if err := cb(ServerGroupCoordinators, d.Spec.Coordinators, &status.Members.Coordinators); err != nil {
return maskAny(err)
}
if err := cb(ServerGroupSyncMasters, d.Spec.SyncMasters, &status.Members.SyncMasters); err != nil {
return maskAny(err)
}
if err := cb(ServerGroupSyncWorkers, d.Spec.SyncWorkers, &status.Members.SyncWorkers); err != nil {
return maskAny(err)
}
return nil
}

View file

@ -1,50 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Lars Maier
//
package v1alpha
type DeploymentRestoreState string
const (
DeploymentRestoreStateRestoring DeploymentRestoreState = "Restoring"
DeploymentRestoreStateRestored DeploymentRestoreState = "Restored"
DeploymentRestoreStateRestoreFailed DeploymentRestoreState = "RestoreFailed"
)
type DeploymentRestoreResult struct {
RequestedFrom string `json:"requestedFrom"`
State DeploymentRestoreState `json:"state"`
Message string `json:"message,omitempty"`
}
func (dr *DeploymentRestoreResult) Equal(other *DeploymentRestoreResult) bool {
if dr == nil {
return other == nil
}
if other == nil {
return false
}
return dr.RequestedFrom == other.RequestedFrom &&
dr.Message == other.Message &&
dr.State == other.State
}

View file

@ -1,104 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"github.com/pkg/errors"
)
// DeploymentMode specifies the type of ArangoDB deployment to create.
type DeploymentMode string
const (
// DeploymentModeSingle yields a single server
DeploymentModeSingle DeploymentMode = "Single"
// DeploymentModeActiveFailover yields an agency and a active-failover server pair
DeploymentModeActiveFailover DeploymentMode = "ActiveFailover"
// DeploymentModeCluster yields an full cluster (agency, dbservers & coordinators)
DeploymentModeCluster DeploymentMode = "Cluster"
)
// Validate the mode.
// Return errors when validation fails, nil on success.
func (m DeploymentMode) Validate() error {
switch m {
case DeploymentModeSingle, DeploymentModeActiveFailover, DeploymentModeCluster:
return nil
default:
return maskAny(errors.Wrapf(ValidationError, "Unknown deployment mode: '%s'", string(m)))
}
}
// HasSingleServers returns true when the given mode is "Single" or "ActiveFailover".
func (m DeploymentMode) HasSingleServers() bool {
return m == DeploymentModeSingle || m == DeploymentModeActiveFailover
}
// HasAgents returns true when the given mode is "ActiveFailover" or "Cluster".
func (m DeploymentMode) HasAgents() bool {
return m == DeploymentModeActiveFailover || m == DeploymentModeCluster
}
// HasDBServers returns true when the given mode is "Cluster".
func (m DeploymentMode) HasDBServers() bool {
return m == DeploymentModeCluster
}
// HasCoordinators returns true when the given mode is "Cluster".
func (m DeploymentMode) HasCoordinators() bool {
return m == DeploymentModeCluster
}
// SupportsSync returns true when the given mode supports dc2dc replication.
func (m DeploymentMode) SupportsSync() bool {
return m == DeploymentModeCluster
}
// IsCluster returns true if the deployment mode is cluster
func (m DeploymentMode) IsCluster() bool {
return m == DeploymentModeCluster
}
// NewMode returns a reference to a string with given value.
func NewMode(input DeploymentMode) *DeploymentMode {
return &input
}
// NewModeOrNil returns nil if input is nil, otherwise returns a clone of the given value.
func NewModeOrNil(input *DeploymentMode) *DeploymentMode {
if input == nil {
return nil
}
return NewMode(*input)
}
// ModeOrDefault returns the default value (or empty string) if input is nil, otherwise returns the referenced value.
func ModeOrDefault(input *DeploymentMode, defaultValue ...DeploymentMode) DeploymentMode {
if input == nil {
if len(defaultValue) > 0 {
return defaultValue[0]
}
return ""
}
return *input
}

View file

@ -1,68 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestDeploymentModeValidate(t *testing.T) {
// Valid
assert.Nil(t, DeploymentMode("Single").Validate())
assert.Nil(t, DeploymentMode("ActiveFailover").Validate())
assert.Nil(t, DeploymentMode("Cluster").Validate())
// Not valid
assert.Error(t, DeploymentMode("").Validate())
assert.Error(t, DeploymentMode(" cluster").Validate())
assert.Error(t, DeploymentMode("singles").Validate())
assert.Error(t, DeploymentMode("single").Validate())
assert.Error(t, DeploymentMode("activefailover").Validate())
assert.Error(t, DeploymentMode("cluster").Validate())
}
func TestDeploymentModeHasX(t *testing.T) {
assert.True(t, DeploymentModeSingle.HasSingleServers())
assert.True(t, DeploymentModeActiveFailover.HasSingleServers())
assert.False(t, DeploymentModeCluster.HasSingleServers())
assert.False(t, DeploymentModeSingle.HasAgents())
assert.True(t, DeploymentModeActiveFailover.HasAgents())
assert.True(t, DeploymentModeCluster.HasAgents())
assert.False(t, DeploymentModeSingle.HasDBServers())
assert.False(t, DeploymentModeActiveFailover.HasDBServers())
assert.True(t, DeploymentModeCluster.HasDBServers())
assert.False(t, DeploymentModeSingle.HasCoordinators())
assert.False(t, DeploymentModeActiveFailover.HasCoordinators())
assert.True(t, DeploymentModeCluster.HasCoordinators())
}
func TestDeploymentModeSupportsSync(t *testing.T) {
assert.False(t, DeploymentModeSingle.SupportsSync())
assert.False(t, DeploymentModeActiveFailover.SupportsSync())
assert.True(t, DeploymentModeCluster.SupportsSync())
}

View file

@ -1,42 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
// DeploymentPhase is a strongly typed lifetime phase of a deployment
type DeploymentPhase string
const (
// DeploymentPhaseNone indicates that the phase is not set yet
DeploymentPhaseNone DeploymentPhase = ""
// DeploymentPhaseRunning indicates that the deployment is under control of the
// ArangoDeployment operator.
DeploymentPhaseRunning DeploymentPhase = "Running"
// DeploymentPhaseFailed indicates that a deployment is in a failed state
// from which automatic recovery is impossible. Inspect `Reason` for more info.
DeploymentPhaseFailed DeploymentPhase = "Failed"
)
// IsFailed returns true if given state is DeploymentStateFailed
func (cs DeploymentPhase) IsFailed() bool {
return cs == DeploymentPhaseFailed
}

View file

@ -1,35 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestDeploymentPhaseIsFailed(t *testing.T) {
assert.False(t, DeploymentPhaseNone.IsFailed())
assert.True(t, DeploymentPhaseFailed.IsFailed())
assert.False(t, DeploymentPhaseRunning.IsFailed())
}

View file

@ -1,414 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"reflect"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
)
const (
defaultImage = "arangodb/arangodb:latest"
)
// validatePullPolicy the image pull policy.
// Return errors when validation fails, nil on success.
func validatePullPolicy(v v1.PullPolicy) error {
switch v {
case "", v1.PullAlways, v1.PullNever, v1.PullIfNotPresent:
return nil
default:
return maskAny(errors.Wrapf(ValidationError, "Unknown pull policy: '%s'", string(v)))
}
}
// DeploymentSpec contains the spec part of a ArangoDeployment resource.
type DeploymentSpec struct {
Mode *DeploymentMode `json:"mode,omitempty"`
Environment *Environment `json:"environment,omitempty"`
StorageEngine *StorageEngine `json:"storageEngine,omitempty"`
Image *string `json:"image,omitempty"`
ImagePullPolicy *v1.PullPolicy `json:"imagePullPolicy,omitempty"`
ImagePullSecrets []string `json:"imagePullSecrets,omitempty"`
DowntimeAllowed *bool `json:"downtimeAllowed,omitempty"`
DisableIPv6 *bool `json:"disableIPv6,omitempty"`
NetworkAttachedVolumes *bool `json:"networkAttachedVolumes,omitempty"`
// Annotations specified the annotations added to Pods in this group.
Annotations map[string]string `json:"annotations,omitempty"`
RestoreFrom *string `json:"restoreFrom,omitempty"`
ExternalAccess ExternalAccessSpec `json:"externalAccess"`
RocksDB RocksDBSpec `json:"rocksdb"`
Authentication AuthenticationSpec `json:"auth"`
TLS TLSSpec `json:"tls"`
Sync SyncSpec `json:"sync"`
License LicenseSpec `json:"license"`
Metrics MetricsSpec `json:"metrics"`
Lifecycle LifecycleSpec `json:"lifecycle,omitempty"`
Single ServerGroupSpec `json:"single"`
Agents ServerGroupSpec `json:"agents"`
DBServers ServerGroupSpec `json:"dbservers"`
Coordinators ServerGroupSpec `json:"coordinators"`
SyncMasters ServerGroupSpec `json:"syncmasters"`
SyncWorkers ServerGroupSpec `json:"syncworkers"`
Chaos ChaosSpec `json:"chaos"`
Bootstrap BootstrapSpec `json:"bootstrap,omitempty"`
}
// GetRestoreFrom returns the restore from string or empty string if not set
func (s *DeploymentSpec) GetRestoreFrom() string {
return util.StringOrDefault(s.RestoreFrom)
}
// HasRestoreFrom returns true if RestoreFrom is set
func (s *DeploymentSpec) HasRestoreFrom() bool {
return s.RestoreFrom != nil
}
// Equal compares two DeploymentSpec
func (s *DeploymentSpec) Equal(other *DeploymentSpec) bool {
return reflect.DeepEqual(s, other)
}
// GetMode returns the value of mode.
func (s DeploymentSpec) GetMode() DeploymentMode {
return ModeOrDefault(s.Mode)
}
// GetEnvironment returns the value of environment.
func (s DeploymentSpec) GetEnvironment() Environment {
return EnvironmentOrDefault(s.Environment)
}
// GetAnnotations returns the annotations of this group
func (s DeploymentSpec) GetAnnotations() map[string]string {
return s.Annotations
}
// GetStorageEngine returns the value of storageEngine.
func (s DeploymentSpec) GetStorageEngine() StorageEngine {
return StorageEngineOrDefault(s.StorageEngine)
}
// GetImage returns the value of image.
func (s DeploymentSpec) GetImage() string {
return util.StringOrDefault(s.Image)
}
// GetSyncImage returns, if set, Sync.Image or the default image.
func (s DeploymentSpec) GetSyncImage() string {
if s.Sync.HasSyncImage() {
return s.Sync.GetSyncImage()
}
return s.GetImage()
}
// GetImagePullPolicy returns the value of imagePullPolicy.
func (s DeploymentSpec) GetImagePullPolicy() v1.PullPolicy {
return util.PullPolicyOrDefault(s.ImagePullPolicy)
}
// IsDowntimeAllowed returns the value of downtimeAllowed.
func (s DeploymentSpec) IsDowntimeAllowed() bool {
return util.BoolOrDefault(s.DowntimeAllowed)
}
// IsDisableIPv6 returns the value of disableIPv6.
func (s DeploymentSpec) IsDisableIPv6() bool {
return util.BoolOrDefault(s.DisableIPv6)
}
// IsNetworkAttachedVolumes returns the value of networkAttachedVolumes, default false
func (s DeploymentSpec) IsNetworkAttachedVolumes() bool {
return util.BoolOrDefault(s.NetworkAttachedVolumes, false)
}
// GetListenAddr returns "[::]" or "0.0.0.0" depending on IsDisableIPv6
func (s DeploymentSpec) GetListenAddr() string {
if s.IsDisableIPv6() {
return "0.0.0.0"
}
return "[::]"
}
// IsAuthenticated returns true when authentication is enabled
func (s DeploymentSpec) IsAuthenticated() bool {
return s.Authentication.IsAuthenticated()
}
// IsSecure returns true when SSL is enabled
func (s DeploymentSpec) IsSecure() bool {
return s.TLS.IsSecure()
}
// GetServerGroupSpec returns the server group spec (from this
// deployment spec) for the given group.
func (s DeploymentSpec) GetServerGroupSpec(group ServerGroup) ServerGroupSpec {
switch group {
case ServerGroupSingle:
return s.Single
case ServerGroupAgents:
return s.Agents
case ServerGroupDBServers:
return s.DBServers
case ServerGroupCoordinators:
return s.Coordinators
case ServerGroupSyncMasters:
return s.SyncMasters
case ServerGroupSyncWorkers:
return s.SyncWorkers
default:
return ServerGroupSpec{}
}
}
// UpdateServerGroupSpec returns the server group spec (from this
// deployment spec) for the given group.
func (s *DeploymentSpec) UpdateServerGroupSpec(group ServerGroup, gspec ServerGroupSpec) {
switch group {
case ServerGroupSingle:
s.Single = gspec
case ServerGroupAgents:
s.Agents = gspec
case ServerGroupDBServers:
s.DBServers = gspec
case ServerGroupCoordinators:
s.Coordinators = gspec
case ServerGroupSyncMasters:
s.SyncMasters = gspec
case ServerGroupSyncWorkers:
s.SyncWorkers = gspec
}
}
// SetDefaults fills in default values when a field is not specified.
func (s *DeploymentSpec) SetDefaults(deploymentName string) {
if s.GetMode() == "" {
s.Mode = NewMode(DeploymentModeCluster)
}
if s.GetEnvironment() == "" {
s.Environment = NewEnvironment(EnvironmentDevelopment)
}
if s.GetStorageEngine() == "" {
s.StorageEngine = NewStorageEngine(StorageEngineRocksDB)
}
if s.GetImage() == "" && s.IsDevelopment() {
s.Image = util.NewString(defaultImage)
}
if s.GetImagePullPolicy() == "" {
s.ImagePullPolicy = util.NewPullPolicy(v1.PullIfNotPresent)
}
s.ExternalAccess.SetDefaults()
s.RocksDB.SetDefaults()
s.Authentication.SetDefaults(deploymentName + "-jwt")
s.TLS.SetDefaults(deploymentName + "-ca")
s.Sync.SetDefaults(deploymentName+"-sync-jwt", deploymentName+"-sync-client-auth-ca", deploymentName+"-sync-ca", deploymentName+"-sync-mt")
s.Single.SetDefaults(ServerGroupSingle, s.GetMode().HasSingleServers(), s.GetMode())
s.Agents.SetDefaults(ServerGroupAgents, s.GetMode().HasAgents(), s.GetMode())
s.DBServers.SetDefaults(ServerGroupDBServers, s.GetMode().HasDBServers(), s.GetMode())
s.Coordinators.SetDefaults(ServerGroupCoordinators, s.GetMode().HasCoordinators(), s.GetMode())
s.SyncMasters.SetDefaults(ServerGroupSyncMasters, s.Sync.IsEnabled(), s.GetMode())
s.SyncWorkers.SetDefaults(ServerGroupSyncWorkers, s.Sync.IsEnabled(), s.GetMode())
s.Metrics.SetDefaults(deploymentName+"-exporter-jwt-token", s.Authentication.IsAuthenticated())
s.Chaos.SetDefaults()
s.Bootstrap.SetDefaults(deploymentName)
}
// SetDefaultsFrom fills unspecified fields with a value from given source spec.
func (s *DeploymentSpec) SetDefaultsFrom(source DeploymentSpec) {
if s.Mode == nil {
s.Mode = NewModeOrNil(source.Mode)
}
if s.Environment == nil {
s.Environment = NewEnvironmentOrNil(source.Environment)
}
if s.StorageEngine == nil {
s.StorageEngine = NewStorageEngineOrNil(source.StorageEngine)
}
if s.Image == nil {
s.Image = util.NewStringOrNil(source.Image)
}
if s.ImagePullPolicy == nil {
s.ImagePullPolicy = util.NewPullPolicyOrNil(source.ImagePullPolicy)
}
if s.DowntimeAllowed == nil {
s.DowntimeAllowed = util.NewBoolOrNil(source.DowntimeAllowed)
}
if s.DisableIPv6 == nil {
s.DisableIPv6 = util.NewBoolOrNil(source.DisableIPv6)
}
s.License.SetDefaultsFrom(source.License)
s.ExternalAccess.SetDefaultsFrom(source.ExternalAccess)
s.RocksDB.SetDefaultsFrom(source.RocksDB)
s.Authentication.SetDefaultsFrom(source.Authentication)
s.TLS.SetDefaultsFrom(source.TLS)
s.Sync.SetDefaultsFrom(source.Sync)
s.Single.SetDefaultsFrom(source.Single)
s.Agents.SetDefaultsFrom(source.Agents)
s.DBServers.SetDefaultsFrom(source.DBServers)
s.Coordinators.SetDefaultsFrom(source.Coordinators)
s.SyncMasters.SetDefaultsFrom(source.SyncMasters)
s.SyncWorkers.SetDefaultsFrom(source.SyncWorkers)
s.Metrics.SetDefaultsFrom(source.Metrics)
s.Lifecycle.SetDefaultsFrom(source.Lifecycle)
s.Chaos.SetDefaultsFrom(source.Chaos)
s.Bootstrap.SetDefaultsFrom(source.Bootstrap)
}
// Validate the specification.
// Return errors when validation fails, nil on success.
func (s *DeploymentSpec) Validate() error {
if err := s.GetMode().Validate(); err != nil {
return maskAny(errors.Wrap(err, "spec.mode"))
}
if err := s.GetEnvironment().Validate(); err != nil {
return maskAny(errors.Wrap(err, "spec.environment"))
}
if err := s.GetStorageEngine().Validate(); err != nil {
return maskAny(errors.Wrap(err, "spec.storageEngine"))
}
if err := validatePullPolicy(s.GetImagePullPolicy()); err != nil {
return maskAny(errors.Wrap(err, "spec.imagePullPolicy"))
}
if s.GetImage() == "" {
return maskAny(errors.Wrapf(ValidationError, "spec.image must be set"))
}
if err := s.ExternalAccess.Validate(); err != nil {
return maskAny(errors.Wrap(err, "spec.externalAccess"))
}
if err := s.RocksDB.Validate(); err != nil {
return maskAny(errors.Wrap(err, "spec.rocksdb"))
}
if err := s.Authentication.Validate(false); err != nil {
return maskAny(errors.Wrap(err, "spec.auth"))
}
if err := s.TLS.Validate(); err != nil {
return maskAny(errors.Wrap(err, "spec.tls"))
}
if err := s.Sync.Validate(s.GetMode()); err != nil {
return maskAny(errors.Wrap(err, "spec.sync"))
}
if err := s.Single.Validate(ServerGroupSingle, s.GetMode().HasSingleServers(), s.GetMode(), s.GetEnvironment()); err != nil {
return maskAny(err)
}
if err := s.Agents.Validate(ServerGroupAgents, s.GetMode().HasAgents(), s.GetMode(), s.GetEnvironment()); err != nil {
return maskAny(err)
}
if err := s.DBServers.Validate(ServerGroupDBServers, s.GetMode().HasDBServers(), s.GetMode(), s.GetEnvironment()); err != nil {
return maskAny(err)
}
if err := s.Coordinators.Validate(ServerGroupCoordinators, s.GetMode().HasCoordinators(), s.GetMode(), s.GetEnvironment()); err != nil {
return maskAny(err)
}
if err := s.SyncMasters.Validate(ServerGroupSyncMasters, s.Sync.IsEnabled(), s.GetMode(), s.GetEnvironment()); err != nil {
return maskAny(err)
}
if err := s.SyncWorkers.Validate(ServerGroupSyncWorkers, s.Sync.IsEnabled(), s.GetMode(), s.GetEnvironment()); err != nil {
return maskAny(err)
}
if err := s.Metrics.Validate(); err != nil {
return maskAny(errors.Wrap(err, "spec.metrics"))
}
if err := s.Chaos.Validate(); err != nil {
return maskAny(errors.Wrap(err, "spec.chaos"))
}
if err := s.License.Validate(); err != nil {
return maskAny(errors.Wrap(err, "spec.licenseKey"))
}
if err := s.Bootstrap.Validate(); err != nil {
return maskAny(err)
}
return nil
}
// IsDevelopment returns true when the spec contains a Development environment.
func (s DeploymentSpec) IsDevelopment() bool {
return s.GetEnvironment() == EnvironmentDevelopment
}
// IsProduction returns true when the spec contains a Production environment.
func (s DeploymentSpec) IsProduction() bool {
return s.GetEnvironment() == EnvironmentProduction
}
// ResetImmutableFields replaces all immutable fields in the given target with values from the source spec.
// It returns a list of fields that have been reset.
// Field names are relative to `spec.`.
func (s DeploymentSpec) ResetImmutableFields(target *DeploymentSpec) []string {
var resetFields []string
if s.GetMode() != target.GetMode() {
target.Mode = NewModeOrNil(s.Mode)
resetFields = append(resetFields, "mode")
}
if s.GetStorageEngine() != target.GetStorageEngine() {
target.StorageEngine = NewStorageEngineOrNil(s.StorageEngine)
resetFields = append(resetFields, "storageEngine")
}
if s.IsDisableIPv6() != target.IsDisableIPv6() {
target.DisableIPv6 = util.NewBoolOrNil(s.DisableIPv6)
resetFields = append(resetFields, "disableIPv6")
}
if l := s.ExternalAccess.ResetImmutableFields("externalAccess", &target.ExternalAccess); l != nil {
resetFields = append(resetFields, l...)
}
if l := s.RocksDB.ResetImmutableFields("rocksdb", &target.RocksDB); l != nil {
resetFields = append(resetFields, l...)
}
if l := s.Authentication.ResetImmutableFields("auth", &target.Authentication); l != nil {
resetFields = append(resetFields, l...)
}
if l := s.Sync.ResetImmutableFields("sync", &target.Sync); l != nil {
resetFields = append(resetFields, l...)
}
if l := s.Single.ResetImmutableFields(ServerGroupSingle, "single", &target.Single); l != nil {
resetFields = append(resetFields, l...)
}
if l := s.Agents.ResetImmutableFields(ServerGroupAgents, "agents", &target.Agents); l != nil {
resetFields = append(resetFields, l...)
}
if l := s.DBServers.ResetImmutableFields(ServerGroupDBServers, "dbservers", &target.DBServers); l != nil {
resetFields = append(resetFields, l...)
}
if l := s.Coordinators.ResetImmutableFields(ServerGroupCoordinators, "coordinators", &target.Coordinators); l != nil {
resetFields = append(resetFields, l...)
}
if l := s.SyncMasters.ResetImmutableFields(ServerGroupSyncMasters, "syncmasters", &target.SyncMasters); l != nil {
resetFields = append(resetFields, l...)
}
if l := s.SyncWorkers.ResetImmutableFields(ServerGroupSyncWorkers, "syncworkers", &target.SyncWorkers); l != nil {
resetFields = append(resetFields, l...)
}
if l := s.Metrics.ResetImmutableFields("metrics", &target.Metrics); l != nil {
resetFields = append(resetFields, l...)
}
return resetFields
}

View file

@ -1,124 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"testing"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/stretchr/testify/assert"
v1 "k8s.io/api/core/v1"
)
func TestDeploymentSpecValidate(t *testing.T) {
// TODO
}
func TestDeploymentSpecSetDefaults(t *testing.T) {
def := func(spec DeploymentSpec) DeploymentSpec {
spec.SetDefaults("test")
return spec
}
assert.Equal(t, "arangodb/arangodb:latest", def(DeploymentSpec{}).GetImage())
}
func TestDeploymentSpecResetImmutableFields(t *testing.T) {
tests := []struct {
Original DeploymentSpec
Target DeploymentSpec
Expected DeploymentSpec
ApplyDefaults bool
Result []string
}{
// Valid "changes"
{
DeploymentSpec{Image: util.NewString("foo")},
DeploymentSpec{Image: util.NewString("foo2")},
DeploymentSpec{Image: util.NewString("foo2")},
false,
nil,
},
{
DeploymentSpec{Image: util.NewString("foo")},
DeploymentSpec{Image: util.NewString("foo2")},
DeploymentSpec{Image: util.NewString("foo2")},
true,
nil,
},
{
DeploymentSpec{ImagePullPolicy: util.NewPullPolicy(v1.PullAlways)},
DeploymentSpec{ImagePullPolicy: util.NewPullPolicy(v1.PullNever)},
DeploymentSpec{ImagePullPolicy: util.NewPullPolicy(v1.PullNever)},
false,
nil,
},
{
DeploymentSpec{ImagePullPolicy: util.NewPullPolicy(v1.PullAlways)},
DeploymentSpec{ImagePullPolicy: util.NewPullPolicy(v1.PullNever)},
DeploymentSpec{ImagePullPolicy: util.NewPullPolicy(v1.PullNever)},
true,
nil,
},
// Invalid changes
{
DeploymentSpec{Mode: NewMode(DeploymentModeSingle)},
DeploymentSpec{Mode: NewMode(DeploymentModeCluster)},
DeploymentSpec{Mode: NewMode(DeploymentModeSingle)},
false,
[]string{"mode"},
},
{
DeploymentSpec{Mode: NewMode(DeploymentModeSingle)},
DeploymentSpec{Mode: NewMode(DeploymentModeCluster)},
DeploymentSpec{Mode: NewMode(DeploymentModeSingle)},
true,
[]string{"mode", "agents.count"},
},
{
DeploymentSpec{DisableIPv6: util.NewBool(false)},
DeploymentSpec{DisableIPv6: util.NewBool(true)},
DeploymentSpec{DisableIPv6: util.NewBool(false)},
false,
[]string{"disableIPv6"},
},
}
for _, test := range tests {
if test.ApplyDefaults {
test.Original.SetDefaults("foo")
test.Expected.SetDefaults("foo")
test.Target.SetDefaultsFrom(test.Original)
test.Target.SetDefaults("foo")
}
result := test.Original.ResetImmutableFields(&test.Target)
if test.ApplyDefaults {
if len(result) > 0 {
test.Target.SetDefaults("foo")
}
}
assert.Equal(t, test.Result, result)
assert.Equal(t, test.Expected, test.Target)
}
}

View file

@ -1,95 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"github.com/arangodb/kube-arangodb/pkg/util"
)
// DeploymentStatus contains the status part of a Cluster resource.
type DeploymentStatus struct {
// Phase holds the current lifetime phase of the deployment
Phase DeploymentPhase `json:"phase"`
// Reason contains a human readable reason for reaching the current state (can be empty)
Reason string `json:"reason,omitempty"` // Reason for current state
// ServiceName holds the name of the Service a client can use (inside the k8s cluster)
// to access ArangoDB.
ServiceName string `json:"serviceName,omitempty"`
// SyncServiceName holds the name of the Service a client can use (inside the k8s cluster)
// to access syncmasters (only set when dc2dc synchronization is enabled).
SyncServiceName string `json:"syncServiceName,omitempty"`
ExporterServiceName string `json:"exporterServiceName,omitempty"`
ExporterServiceMonitorName string `json:"exporterServiceMonitorName,omitempty"`
Restore *DeploymentRestoreResult `json:"restore,omitempty"`
// Images holds a list of ArangoDB images with their ID and ArangoDB version.
Images ImageInfoList `json:"arangodb-images,omitempty"`
// Image that is currently being used when new pods are created
CurrentImage *ImageInfo `json:"current-image,omitempty"`
// Members holds the status for all members in all server groups
Members DeploymentStatusMembers `json:"members"`
// Conditions specific to the entire deployment
Conditions ConditionList `json:"conditions,omitempty"`
// Plan to update this deployment
Plan Plan `json:"plan,omitempty"`
// AcceptedSpec contains the last specification that was accepted by the operator.
AcceptedSpec *DeploymentSpec `json:"accepted-spec,omitempty"`
// SecretHashes keeps a sha256 hash of secret values, so we can
// detect changes in secret values.
SecretHashes *SecretHashes `json:"secret-hashes,omitempty"`
// ForceStatusReload if set to true forces a reload of the status from the custom resource.
ForceStatusReload *bool `json:"force-status-reload,omitempty"`
}
// Equal checks for equality
func (ds *DeploymentStatus) Equal(other DeploymentStatus) bool {
return ds.Phase == other.Phase &&
ds.Reason == other.Reason &&
ds.ServiceName == other.ServiceName &&
ds.SyncServiceName == other.SyncServiceName &&
ds.ExporterServiceName == other.ExporterServiceName &&
ds.ExporterServiceMonitorName == other.ExporterServiceMonitorName &&
ds.Images.Equal(other.Images) &&
ds.Restore.Equal(other.Restore) &&
ds.CurrentImage.Equal(other.CurrentImage) &&
ds.Members.Equal(other.Members) &&
ds.Conditions.Equal(other.Conditions) &&
ds.Plan.Equal(other.Plan) &&
ds.AcceptedSpec.Equal(other.AcceptedSpec) &&
ds.SecretHashes.Equal(other.SecretHashes)
}
// IsForceReload returns true if ForceStatusReload is set to true
func (ds *DeploymentStatus) IsForceReload() bool {
return util.BoolOrDefault(ds.ForceStatusReload, false)
}

View file

@ -1,265 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"github.com/pkg/errors"
)
// DeploymentStatusMembers holds the member status of all server groups
type DeploymentStatusMembers struct {
Single MemberStatusList `json:"single,omitempty"`
Agents MemberStatusList `json:"agents,omitempty"`
DBServers MemberStatusList `json:"dbservers,omitempty"`
Coordinators MemberStatusList `json:"coordinators,omitempty"`
SyncMasters MemberStatusList `json:"syncmasters,omitempty"`
SyncWorkers MemberStatusList `json:"syncworkers,omitempty"`
}
// Equal checks for equality
func (ds DeploymentStatusMembers) Equal(other DeploymentStatusMembers) bool {
return ds.Single.Equal(other.Single) &&
ds.Agents.Equal(other.Agents) &&
ds.DBServers.Equal(other.DBServers) &&
ds.Coordinators.Equal(other.Coordinators) &&
ds.SyncMasters.Equal(other.SyncMasters) &&
ds.SyncWorkers.Equal(other.SyncWorkers)
}
// ContainsID returns true if the given set of members contains a member with given ID.
func (ds DeploymentStatusMembers) ContainsID(id string) bool {
return ds.Single.ContainsID(id) ||
ds.Agents.ContainsID(id) ||
ds.DBServers.ContainsID(id) ||
ds.Coordinators.ContainsID(id) ||
ds.SyncMasters.ContainsID(id) ||
ds.SyncWorkers.ContainsID(id)
}
// ElementByID returns the element in the given list that has the given ID and true.
// If no such element exists, false is returned.
func (ds DeploymentStatusMembers) ElementByID(id string) (MemberStatus, ServerGroup, bool) {
if result, found := ds.Single.ElementByID(id); found {
return result, ServerGroupSingle, true
}
if result, found := ds.Agents.ElementByID(id); found {
return result, ServerGroupAgents, true
}
if result, found := ds.DBServers.ElementByID(id); found {
return result, ServerGroupDBServers, true
}
if result, found := ds.Coordinators.ElementByID(id); found {
return result, ServerGroupCoordinators, true
}
if result, found := ds.SyncMasters.ElementByID(id); found {
return result, ServerGroupSyncMasters, true
}
if result, found := ds.SyncWorkers.ElementByID(id); found {
return result, ServerGroupSyncWorkers, true
}
return MemberStatus{}, 0, false
}
// ForeachServerGroup calls the given callback for all server groups.
// If the callback returns an error, this error is returned and the callback is
// not called for the remaining groups.
func (ds DeploymentStatusMembers) ForeachServerGroup(cb func(group ServerGroup, list MemberStatusList) error) error {
if err := cb(ServerGroupSingle, ds.Single); err != nil {
return maskAny(err)
}
if err := cb(ServerGroupAgents, ds.Agents); err != nil {
return maskAny(err)
}
if err := cb(ServerGroupDBServers, ds.DBServers); err != nil {
return maskAny(err)
}
if err := cb(ServerGroupCoordinators, ds.Coordinators); err != nil {
return maskAny(err)
}
if err := cb(ServerGroupSyncMasters, ds.SyncMasters); err != nil {
return maskAny(err)
}
if err := cb(ServerGroupSyncWorkers, ds.SyncWorkers); err != nil {
return maskAny(err)
}
return nil
}
// MemberStatusByPodName returns a reference to the element in the given set of lists that has the given pod name.
// If no such element exists, nil is returned.
func (ds DeploymentStatusMembers) MemberStatusByPodName(podName string) (MemberStatus, ServerGroup, bool) {
if result, found := ds.Single.ElementByPodName(podName); found {
return result, ServerGroupSingle, true
}
if result, found := ds.Agents.ElementByPodName(podName); found {
return result, ServerGroupAgents, true
}
if result, found := ds.DBServers.ElementByPodName(podName); found {
return result, ServerGroupDBServers, true
}
if result, found := ds.Coordinators.ElementByPodName(podName); found {
return result, ServerGroupCoordinators, true
}
if result, found := ds.SyncMasters.ElementByPodName(podName); found {
return result, ServerGroupSyncMasters, true
}
if result, found := ds.SyncWorkers.ElementByPodName(podName); found {
return result, ServerGroupSyncWorkers, true
}
return MemberStatus{}, 0, false
}
// MemberStatusByPVCName returns a reference to the element in the given set of lists that has the given PVC name.
// If no such element exists, nil is returned.
func (ds DeploymentStatusMembers) MemberStatusByPVCName(pvcName string) (MemberStatus, ServerGroup, bool) {
if result, found := ds.Single.ElementByPVCName(pvcName); found {
return result, ServerGroupSingle, true
}
if result, found := ds.Agents.ElementByPVCName(pvcName); found {
return result, ServerGroupAgents, true
}
if result, found := ds.DBServers.ElementByPVCName(pvcName); found {
return result, ServerGroupDBServers, true
}
// Note: Other server groups do not have PVC's so we can skip them.
return MemberStatus{}, 0, false
}
// Add adds the given status in the given group.
func (ds *DeploymentStatusMembers) Add(status MemberStatus, group ServerGroup) error {
var err error
switch group {
case ServerGroupSingle:
err = ds.Single.add(status)
case ServerGroupAgents:
err = ds.Agents.add(status)
case ServerGroupDBServers:
err = ds.DBServers.add(status)
case ServerGroupCoordinators:
err = ds.Coordinators.add(status)
case ServerGroupSyncMasters:
err = ds.SyncMasters.add(status)
case ServerGroupSyncWorkers:
err = ds.SyncWorkers.add(status)
default:
return maskAny(errors.Wrapf(NotFoundError, "ServerGroup %d is not known", group))
}
if err != nil {
return maskAny(err)
}
return nil
}
// Update updates the given status in the given group.
func (ds *DeploymentStatusMembers) Update(status MemberStatus, group ServerGroup) error {
var err error
switch group {
case ServerGroupSingle:
err = ds.Single.update(status)
case ServerGroupAgents:
err = ds.Agents.update(status)
case ServerGroupDBServers:
err = ds.DBServers.update(status)
case ServerGroupCoordinators:
err = ds.Coordinators.update(status)
case ServerGroupSyncMasters:
err = ds.SyncMasters.update(status)
case ServerGroupSyncWorkers:
err = ds.SyncWorkers.update(status)
default:
return maskAny(errors.Wrapf(NotFoundError, "ServerGroup %d is not known", group))
}
if err != nil {
return maskAny(err)
}
return nil
}
// RemoveByID a member with given ID from the given group.
// Returns a NotFoundError if the ID of the given member or group cannot be found.
func (ds *DeploymentStatusMembers) RemoveByID(id string, group ServerGroup) error {
var err error
switch group {
case ServerGroupSingle:
err = ds.Single.removeByID(id)
case ServerGroupAgents:
err = ds.Agents.removeByID(id)
case ServerGroupDBServers:
err = ds.DBServers.removeByID(id)
case ServerGroupCoordinators:
err = ds.Coordinators.removeByID(id)
case ServerGroupSyncMasters:
err = ds.SyncMasters.removeByID(id)
case ServerGroupSyncWorkers:
err = ds.SyncWorkers.removeByID(id)
default:
return maskAny(errors.Wrapf(NotFoundError, "ServerGroup %d is not known", group))
}
if err != nil {
return maskAny(err)
}
return nil
}
// AllMembersReady returns true when all members, that must be ready for the given mode, are in the Ready state.
func (ds DeploymentStatusMembers) AllMembersReady(mode DeploymentMode, syncEnabled bool) bool {
syncReady := func() bool {
if syncEnabled {
return ds.SyncMasters.AllMembersReady() && ds.SyncWorkers.AllMembersReady()
}
return true
}
switch mode {
case DeploymentModeSingle:
return ds.Single.MembersReady() > 0
case DeploymentModeActiveFailover:
return ds.Agents.AllMembersReady() && ds.Single.MembersReady() > 0
case DeploymentModeCluster:
return ds.Agents.AllMembersReady() &&
ds.DBServers.AllMembersReady() &&
ds.Coordinators.AllMembersReady() &&
syncReady()
default:
return false
}
}
// MembersOfGroup returns the member list of the given group
func (ds DeploymentStatusMembers) MembersOfGroup(group ServerGroup) MemberStatusList {
switch group {
case ServerGroupSingle:
return ds.Single
case ServerGroupAgents:
return ds.Agents
case ServerGroupDBServers:
return ds.DBServers
case ServerGroupCoordinators:
return ds.Coordinators
case ServerGroupSyncMasters:
return ds.SyncMasters
case ServerGroupSyncWorkers:
return ds.SyncWorkers
default:
return MemberStatusList{}
}
}

View file

@ -1,25 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
// +k8s:deepcopy-gen=package
// +groupName=database.arangodb.com
package v1alpha

View file

@ -1,81 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"time"
"github.com/pkg/errors"
)
// Duration is a period of time, specified in go time.Duration format.
// This is intended to allow human friendly TTL's to be specified.
type Duration string
// Validate the duration.
// Return errors when validation fails, nil on success.
func (d Duration) Validate() error {
if d != "" {
if _, err := time.ParseDuration(string(d)); err != nil {
return maskAny(errors.Wrapf(ValidationError, "Invalid duration: '%s': %s", string(d), err.Error()))
}
}
return nil
}
// AsDuration parses the duration to a time.Duration value.
// In case of a parse error, 0 is returned.
func (d Duration) AsDuration() time.Duration {
if d == "" {
return 0
}
result, err := time.ParseDuration(string(d))
if err != nil {
return 0
}
return result
}
// NewDuration returns a reference to a Duration with given value.
func NewDuration(input Duration) *Duration {
return &input
}
// NewDurationOrNil returns nil if input is nil, otherwise returns a clone of the given value.
func NewDurationOrNil(input *Duration) *Duration {
if input == nil {
return nil
}
return NewDuration(*input)
}
// DurationOrDefault returns the default value (or empty string) if input is nil, otherwise returns the referenced value.
func DurationOrDefault(input *Duration, defaultValue ...Duration) Duration {
if input == nil {
if len(defaultValue) > 0 {
return defaultValue[0]
}
return ""
}
return *input
}

View file

@ -1,77 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"github.com/pkg/errors"
)
// Environment in which to run the cluster
type Environment string
const (
// EnvironmentDevelopment yields a cluster optimized for development
EnvironmentDevelopment Environment = "Development"
// EnvironmentProduction yields a cluster optimized for production
EnvironmentProduction Environment = "Production"
)
// Validate the environment.
// Return errors when validation fails, nil on success.
func (e Environment) Validate() error {
switch e {
case EnvironmentDevelopment, EnvironmentProduction:
return nil
default:
return maskAny(errors.Wrapf(ValidationError, "Unknown environment: '%s'", string(e)))
}
}
// IsProduction returns true when the given environment is a production environment.
func (e Environment) IsProduction() bool {
return e == EnvironmentProduction
}
// NewEnvironment returns a reference to a string with given value.
func NewEnvironment(input Environment) *Environment {
return &input
}
// NewEnvironmentOrNil returns nil if input is nil, otherwise returns a clone of the given value.
func NewEnvironmentOrNil(input *Environment) *Environment {
if input == nil {
return nil
}
return NewEnvironment(*input)
}
// EnvironmentOrDefault returns the default value (or empty string) if input is nil, otherwise returns the referenced value.
func EnvironmentOrDefault(input *Environment, defaultValue ...Environment) Environment {
if input == nil {
if len(defaultValue) > 0 {
return defaultValue[0]
}
return ""
}
return *input
}

View file

@ -1,41 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestEnvironmentValidate(t *testing.T) {
// Valid
assert.Nil(t, Environment("Development").Validate())
assert.Nil(t, Environment("Production").Validate())
// Not valid
assert.Error(t, Environment("").Validate())
assert.Error(t, Environment(" development").Validate())
assert.Error(t, Environment("development").Validate())
assert.Error(t, Environment("production").Validate())
}

View file

@ -1,53 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import "github.com/pkg/errors"
var (
// ValidationError indicates a validation failure
ValidationError = errors.New("validation failed")
// AlreadyExistsError indicates an object that already exists
AlreadyExistsError = errors.New("already exists")
// NotFoundError indicates an object that cannot be found
NotFoundError = errors.New("not found")
maskAny = errors.WithStack
)
// IsValidation return true when the given error is or is caused by a ValidationError.
func IsValidation(err error) bool {
return errors.Cause(err) == ValidationError
}
// IsAlreadyExists return true when the given error is or is caused by a AlreadyExistsError.
func IsAlreadyExists(err error) bool {
return errors.Cause(err) == AlreadyExistsError
}
// IsNotFound return true when the given error is or is caused by a NotFoundError.
func IsNotFound(err error) bool {
return errors.Cause(err) == NotFoundError
}

View file

@ -1,122 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"fmt"
"net"
"net/url"
"github.com/arangodb/kube-arangodb/pkg/util"
)
// ExternalAccessSpec holds configuration for the external access provided for the deployment.
type ExternalAccessSpec struct {
// Type of external access
Type *ExternalAccessType `json:"type,omitempty"`
// Optional port used in case of Auto or NodePort type.
NodePort *int `json:"nodePort,omitempty"`
// Optional IP used to configure a load-balancer on, in case of Auto or LoadBalancer type.
LoadBalancerIP *string `json:"loadBalancerIP,omitempty"`
// If specified and supported by the platform, this will restrict traffic through the cloud-provider
// load-balancer will be restricted to the specified client IPs. This field will be ignored if the
// cloud-provider does not support the feature.
// More info: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/
LoadBalancerSourceRanges []string `json:"loadBalancerSourceRanges,omitempty"`
// Advertised Endpoint is passed to the coordinators/single servers for advertising a specific endpoint
AdvertisedEndpoint *string `json:"advertisedEndpoint,omitempty"`
}
// GetType returns the value of type.
func (s ExternalAccessSpec) GetType() ExternalAccessType {
return ExternalAccessTypeOrDefault(s.Type, ExternalAccessTypeAuto)
}
// GetNodePort returns the value of nodePort.
func (s ExternalAccessSpec) GetNodePort() int {
return util.IntOrDefault(s.NodePort)
}
// GetLoadBalancerIP returns the value of loadBalancerIP.
func (s ExternalAccessSpec) GetLoadBalancerIP() string {
return util.StringOrDefault(s.LoadBalancerIP)
}
// GetAdvertisedEndpoint returns the advertised endpoint or empty string if none was specified
func (s ExternalAccessSpec) GetAdvertisedEndpoint() string {
return util.StringOrDefault(s.AdvertisedEndpoint)
}
// HasAdvertisedEndpoint return whether an advertised endpoint was specified or not
func (s ExternalAccessSpec) HasAdvertisedEndpoint() bool {
return s.AdvertisedEndpoint != nil
}
// Validate the given spec
func (s ExternalAccessSpec) Validate() error {
if err := s.GetType().Validate(); err != nil {
return maskAny(err)
}
if s.AdvertisedEndpoint != nil {
ep := s.GetAdvertisedEndpoint()
if _, err := url.Parse(ep); err != nil {
return maskAny(fmt.Errorf("Failed to parse advertised endpoint '%s': %s", ep, err))
}
}
for _, x := range s.LoadBalancerSourceRanges {
if _, _, err := net.ParseCIDR(x); err != nil {
return maskAny(fmt.Errorf("Failed to parse loadbalancer source range '%s': %s", x, err))
}
}
return nil
}
// SetDefaults fills in missing defaults
func (s *ExternalAccessSpec) SetDefaults() {
}
// SetDefaultsFrom fills unspecified fields with a value from given source spec.
func (s *ExternalAccessSpec) SetDefaultsFrom(source ExternalAccessSpec) {
if s.Type == nil {
s.Type = NewExternalAccessTypeOrNil(source.Type)
}
if s.NodePort == nil {
s.NodePort = util.NewIntOrNil(source.NodePort)
}
if s.LoadBalancerIP == nil {
s.LoadBalancerIP = util.NewStringOrNil(source.LoadBalancerIP)
}
if s.LoadBalancerSourceRanges == nil && len(source.LoadBalancerSourceRanges) > 0 {
s.LoadBalancerSourceRanges = append([]string{}, source.LoadBalancerSourceRanges...)
}
if s.AdvertisedEndpoint == nil {
s.AdvertisedEndpoint = source.AdvertisedEndpoint
}
}
// ResetImmutableFields replaces all immutable fields in the given target with values from the source spec.
// It returns a list of fields that have been reset.
// Field names are relative to given field prefix.
func (s ExternalAccessSpec) ResetImmutableFields(fieldPrefix string, target *ExternalAccessSpec) []string {
return nil
}

View file

@ -1,95 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
)
// ExternalAccessType specifies the type of external access provides for the deployment
type ExternalAccessType string
const (
// ExternalAccessTypeNone yields a cluster with no external access
ExternalAccessTypeNone ExternalAccessType = "None"
// ExternalAccessTypeAuto yields a cluster with an automatic selection for external access
ExternalAccessTypeAuto ExternalAccessType = "Auto"
// ExternalAccessTypeLoadBalancer yields a cluster with a service of type `LoadBalancer` to provide external access
ExternalAccessTypeLoadBalancer ExternalAccessType = "LoadBalancer"
// ExternalAccessTypeNodePort yields a cluster with a service of type `NodePort` to provide external access
ExternalAccessTypeNodePort ExternalAccessType = "NodePort"
)
func (t ExternalAccessType) IsNone() bool { return t == ExternalAccessTypeNone }
func (t ExternalAccessType) IsAuto() bool { return t == ExternalAccessTypeAuto }
func (t ExternalAccessType) IsLoadBalancer() bool { return t == ExternalAccessTypeLoadBalancer }
func (t ExternalAccessType) IsNodePort() bool { return t == ExternalAccessTypeNodePort }
// AsServiceType returns the k8s ServiceType for this ExternalAccessType.
// If type is "Auto", ServiceTypeLoadBalancer is returned.
func (t ExternalAccessType) AsServiceType() v1.ServiceType {
switch t {
case ExternalAccessTypeLoadBalancer, ExternalAccessTypeAuto:
return v1.ServiceTypeLoadBalancer
case ExternalAccessTypeNodePort:
return v1.ServiceTypeNodePort
default:
return ""
}
}
// Validate the type.
// Return errors when validation fails, nil on success.
func (t ExternalAccessType) Validate() error {
switch t {
case ExternalAccessTypeNone, ExternalAccessTypeAuto, ExternalAccessTypeLoadBalancer, ExternalAccessTypeNodePort:
return nil
default:
return maskAny(errors.Wrapf(ValidationError, "Unknown external access type: '%s'", string(t)))
}
}
// NewExternalAccessType returns a reference to a string with given value.
func NewExternalAccessType(input ExternalAccessType) *ExternalAccessType {
return &input
}
// NewExternalAccessTypeOrNil returns nil if input is nil, otherwise returns a clone of the given value.
func NewExternalAccessTypeOrNil(input *ExternalAccessType) *ExternalAccessType {
if input == nil {
return nil
}
return NewExternalAccessType(*input)
}
// ExternalAccessTypeOrDefault returns the default value (or empty string) if input is nil, otherwise returns the referenced value.
func ExternalAccessTypeOrDefault(input *ExternalAccessType, defaultValue ...ExternalAccessType) ExternalAccessType {
if input == nil {
if len(defaultValue) > 0 {
return defaultValue[0]
}
return ""
}
return *input
}

View file

@ -1,108 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import driver "github.com/arangodb/go-driver"
// ImageInfo contains an ID of an image and the ArangoDB version inside the image.
type ImageInfo struct {
Image string `json:"image"` // Human provided name of the image
ImageID string `json:"image-id,omitempty"` // Unique ID (with SHA256) of the image
ArangoDBVersion driver.Version `json:"arangodb-version,omitempty"` // ArangoDB version within the image
Enterprise bool `json:"enterprise,omitempty"` // If set, this is an enterprise image
}
// ImageInfoList is a list of image infos
type ImageInfoList []ImageInfo
// GetByImage returns the info in the given list for the image with given name.
// If not found, false is returned.
func (l ImageInfoList) GetByImage(image string) (ImageInfo, bool) {
for _, x := range l {
if x.Image == image {
return x, true
}
}
return ImageInfo{}, false
}
// GetByImageID returns the info in the given list for the image with given id.
// If not found, false is returned.
func (l ImageInfoList) GetByImageID(imageID string) (ImageInfo, bool) {
for _, x := range l {
if x.ImageID == imageID {
return x, true
}
}
return ImageInfo{}, false
}
// AddOrUpdate adds the given info to the given list, if its image does not exist
// in the list. If the image does exist in the list, its entry is replaced by the given info.
// If not found, false is returned.
func (l *ImageInfoList) AddOrUpdate(info ImageInfo) {
// Look for existing entry
for i, x := range *l {
if x.Image == info.Image {
(*l)[i] = info
return
}
}
// No existing entry found, add it
*l = append(*l, info)
}
// Equal compares to ImageInfo
func (i *ImageInfo) Equal(other *ImageInfo) bool {
if i == nil || other == nil {
return false
} else if i == other {
return true
}
return i.ArangoDBVersion == other.ArangoDBVersion &&
i.Enterprise == other.Enterprise &&
i.Image == other.Image &&
i.ImageID == other.ImageID
}
// Equal compares to ImageInfoList
func (l ImageInfoList) Equal(other ImageInfoList) bool {
if len(l) != len(other) {
return false
}
for i := 0; i < len(l); i++ {
ii, found := l.GetByImageID(l[i].ImageID)
if !found {
return false
}
if !l[i].Equal(&ii) {
return false
}
}
return true
}

View file

@ -1,50 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestImageInfoList(t *testing.T) {
var list ImageInfoList
_, found := list.GetByImage("notfound")
assert.False(t, found)
_, found = list.GetByImageID("id-notfound")
assert.False(t, found)
list.AddOrUpdate(ImageInfo{
Image: "foo",
ImageID: "foo-ID",
ArangoDBVersion: "1.3.4",
})
assert.Len(t, list, 1)
_, found = list.GetByImage("foo")
assert.True(t, found)
_, found = list.GetByImageID("foo-ID")
assert.True(t, found)
}

View file

@ -1,59 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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 v1alpha
import (
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
)
// LicenseSpec holds the license related information
type LicenseSpec struct {
SecretName *string `json:"secretName,omitempty"`
}
// HasSecretName returns true if a license key secret name was set
func (s LicenseSpec) HasSecretName() bool {
return s.SecretName != nil
}
// GetSecretName returns the license key if set. Empty string otherwise.
func (s LicenseSpec) GetSecretName() string {
return util.StringOrDefault(s.SecretName)
}
// Validate validates the LicenseSpec
func (s LicenseSpec) Validate() error {
if s.HasSecretName() {
if err := k8sutil.ValidateResourceName(s.GetSecretName()); err != nil {
return err
}
}
return nil
}
// SetDefaultsFrom fills all values not set in s with values from other
func (s LicenseSpec) SetDefaultsFrom(other LicenseSpec) {
if !s.HasSecretName() {
s.SecretName = util.NewStringOrNil(other.SecretName)
}
}

View file

@ -1,15 +0,0 @@
package v1alpha
import (
"testing"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/stretchr/testify/assert"
)
func TestLicenseSpecValidation(t *testing.T) {
assert.Nil(t, LicenseSpec{SecretName: nil}.Validate())
assert.Nil(t, LicenseSpec{SecretName: util.NewString("some-name")}.Validate())
assert.Error(t, LicenseSpec{SecretName: util.NewString("@@")}.Validate())
}

View file

@ -1,37 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2019 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
//
// Author Tomasz Mielech <tomasz@arangodb.com>
//
package v1alpha
import (
v1 "k8s.io/api/core/v1"
)
type LifecycleSpec struct {
Resources v1.ResourceRequirements `json:"resources,omitempty"`
}
// SetDefaultsFrom fills unspecified fields with a value from given source spec.
func (s *LifecycleSpec) SetDefaultsFrom(source LifecycleSpec) {
setDefaultsFromResourceList(&s.Resources.Limits, source.Resources.Limits)
setDefaultsFromResourceList(&s.Resources.Requests, source.Resources.Requests)
}

View file

@ -1,57 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
// MemberPhase is a strongly typed lifetime phase of a deployment member
type MemberPhase string
const (
// MemberPhaseNone indicates that the state is not set yet
MemberPhaseNone MemberPhase = ""
// MemberPhaseCreated indicates that all resources needed for the member have been created
MemberPhaseCreated MemberPhase = "Created"
// MemberPhaseFailed indicates that the member is gone beyond hope of recovery. It must be replaced with a new member.
MemberPhaseFailed MemberPhase = "Failed"
// MemberPhaseCleanOut indicates that a dbserver is in the process of being cleaned out
MemberPhaseCleanOut MemberPhase = "CleanOut"
// MemberPhaseDrain indicates that a dbserver is in the process of being cleaned out as result of draining a node
MemberPhaseDrain MemberPhase = "Drain"
// MemberPhaseResign indicates that a dbserver is in the process of resigning for a shutdown
MemberPhaseResign MemberPhase = "Resign"
// MemberPhaseShuttingDown indicates that a member is shutting down
MemberPhaseShuttingDown MemberPhase = "ShuttingDown"
// MemberPhaseRotating indicates that a member is being rotated
MemberPhaseRotating MemberPhase = "Rotating"
// MemberPhaseUpgrading indicates that a member is in the process of upgrading its database data format
MemberPhaseUpgrading MemberPhase = "Upgrading"
)
// IsFailed returns true when given phase == "Failed"
func (p MemberPhase) IsFailed() bool {
return p == MemberPhaseFailed
}
// IsCreatedOrDrain returns true when given phase is MemberPhaseCreated or MemberPhaseDrain
func (p MemberPhase) IsCreatedOrDrain() bool {
return p == MemberPhaseCreated || p == MemberPhaseDrain
}

View file

@ -1,131 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"reflect"
"time"
driver "github.com/arangodb/go-driver"
"github.com/arangodb/kube-arangodb/pkg/util"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// MemberStatus holds the current status of a single member (server)
type MemberStatus struct {
// ID holds the unique ID of the member.
// This id is also used within the ArangoDB cluster to identify this server.
ID string `json:"id"`
// Phase holds the current lifetime phase of this member
Phase MemberPhase `json:"phase"`
// CreatedAt holds the creation timestamp of this member.
CreatedAt metav1.Time `json:"created-at"`
// PersistentVolumeClaimName holds the name of the persistent volume claim used for this member (if any).
PersistentVolumeClaimName string `json:"persistentVolumeClaimName,omitempty"`
// PodName holds the name of the Pod that currently runs this member
PodName string `json:"podName,omitempty"`
// Conditions specific to this member
Conditions ConditionList `json:"conditions,omitempty"`
// RecentTerminatons holds the times when this member was recently terminated.
// First entry is the oldest. (do not add omitempty, since we want to be able to switch from a list to an empty list)
RecentTerminations []metav1.Time `json:"recent-terminations"`
// IsInitialized is set after the very first time a pod was created for this member.
// After that, DBServers must have a UUID field or fail.
IsInitialized bool `json:"initialized"`
// CleanoutJobID holds the ID of the agency job for cleaning out this server
CleanoutJobID string `json:"cleanout-job-id,omitempty"`
// SideCarSpecs contains list of specifications specified for side cars
SideCarSpecs map[string]v1.Container `json:"sidecars-specs,omitempty"`
// ArangoVersion holds the ArangoDB version in member
ArangoVersion driver.Version `json:"arango-version,omitempty"`
// ImageId holds the members ArangoDB image ID
ImageID string `json:"image-id,omitempty"`
}
// Equal checks for equality
func (s MemberStatus) Equal(other MemberStatus) bool {
return s.ID == other.ID &&
s.Phase == other.Phase &&
util.TimeCompareEqual(s.CreatedAt, other.CreatedAt) &&
s.PersistentVolumeClaimName == other.PersistentVolumeClaimName &&
s.PodName == other.PodName &&
s.Conditions.Equal(other.Conditions) &&
s.IsInitialized == other.IsInitialized &&
s.CleanoutJobID == other.CleanoutJobID &&
reflect.DeepEqual(s.SideCarSpecs, other.SideCarSpecs) &&
s.ArangoVersion == other.ArangoVersion &&
s.ImageID == other.ImageID
}
// Age returns the duration since the creation timestamp of this member.
func (s MemberStatus) Age() time.Duration {
return time.Since(s.CreatedAt.Time)
}
// RemoveTerminationsBefore removes all recent terminations before the given timestamp.
// It returns the number of terminations that have been removed.
func (s *MemberStatus) RemoveTerminationsBefore(timestamp time.Time) int {
removed := 0
for {
if len(s.RecentTerminations) == 0 {
// Nothing left
return removed
}
if s.RecentTerminations[0].Time.Before(timestamp) {
// Let's remove it
s.RecentTerminations = s.RecentTerminations[1:]
removed++
} else {
// First (oldest) is not before given timestamp, we're done
return removed
}
}
}
// RecentTerminationsSince returns the number of terminations since the given timestamp.
func (s MemberStatus) RecentTerminationsSince(timestamp time.Time) int {
count := 0
for idx := len(s.RecentTerminations) - 1; idx >= 0; idx-- {
if s.RecentTerminations[idx].Time.Before(timestamp) {
// This termination is before the timestamp, so we're done
return count
}
count++
}
return count
}
// IsNotReadySince returns true when the given member has not been ready since the given timestamp.
// That means it:
// - A) Was created before timestamp and never reached a ready state or
// - B) The Ready condition is set to false, and last transision is before timestamp
func (s MemberStatus) IsNotReadySince(timestamp time.Time) bool {
cond, found := s.Conditions.Get(ConditionTypeReady)
if found {
// B
return cond.Status != v1.ConditionTrue && cond.LastTransitionTime.Time.Before(timestamp)
}
// A
return s.CreatedAt.Time.Before(timestamp)
}

View file

@ -1,206 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"math/rand"
"sort"
"time"
"github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
)
// MemberStatusList is a list of MemberStatus entries
type MemberStatusList []MemberStatus
// Equal checks for equality
func (l MemberStatusList) Equal(other MemberStatusList) bool {
if len(l) != len(other) {
return false
}
for i := 0; i < len(l); i++ {
o, found := other.ElementByID(l[i].ID)
if !found {
return false
}
if !l[i].Equal(o) {
return false
}
}
return true
}
// ContainsID returns true if the given list contains a member with given ID.
func (l MemberStatusList) ContainsID(id string) bool {
for _, x := range l {
if x.ID == id {
return true
}
}
return false
}
// ElementByID returns the element in the given list that has the given ID and true.
// If no such element exists, false is returned.
func (l MemberStatusList) ElementByID(id string) (MemberStatus, bool) {
for i, x := range l {
if x.ID == id {
return l[i], true
}
}
return MemberStatus{}, false
}
// ElementByPodName returns the element in the given list that has the given pod name and true.
// If no such element exists, an empty element and false is returned.
func (l MemberStatusList) ElementByPodName(podName string) (MemberStatus, bool) {
for i, x := range l {
if x.PodName == podName {
return l[i], true
}
}
return MemberStatus{}, false
}
// ElementByPVCName returns the element in the given list that has the given PVC name and true.
// If no such element exists, an empty element and false is returned.
func (l MemberStatusList) ElementByPVCName(pvcName string) (MemberStatus, bool) {
for i, x := range l {
if x.PersistentVolumeClaimName == pvcName {
return l[i], true
}
}
return MemberStatus{}, false
}
// Add a member to the list.
// Returns an AlreadyExistsError if the ID of the given member already exists.
func (l *MemberStatusList) add(m MemberStatus) error {
src := *l
for _, x := range src {
if x.ID == m.ID {
return maskAny(errors.Wrapf(AlreadyExistsError, "Member '%s' already exists", m.ID))
}
}
newList := append(src, m)
sort.Slice(newList, func(i, j int) bool { return newList[i].ID < newList[j].ID })
*l = newList
return nil
}
// Update a member in the list.
// Returns a NotFoundError if the ID of the given member cannot be found.
func (l MemberStatusList) update(m MemberStatus) error {
for i, x := range l {
if x.ID == m.ID {
l[i] = m
return nil
}
}
return maskAny(errors.Wrapf(NotFoundError, "Member '%s' is not a member", m.ID))
}
// RemoveByID a member with given ID from the list.
// Returns a NotFoundError if the ID of the given member cannot be found.
func (l *MemberStatusList) removeByID(id string) error {
src := *l
for i, x := range src {
if x.ID == id {
*l = append(src[:i], src[i+1:]...)
return nil
}
}
return maskAny(errors.Wrapf(NotFoundError, "Member '%s' is not a member", id))
}
// SelectMemberToRemove selects a member from the given list that should
// be removed in a scale down action.
// Returns an error if the list is empty.
func (l MemberStatusList) SelectMemberToRemove() (MemberStatus, error) {
if len(l) > 0 {
// Try to find a not ready member
for _, m := range l {
if m.Phase == MemberPhaseNone {
return m, nil
}
}
for _, m := range l {
if !m.Conditions.IsTrue(ConditionTypeReady) {
return m, nil
}
}
// Pick a random member that is in created state
perm := rand.Perm(len(l))
for _, idx := range perm {
m := l[idx]
if m.Phase == MemberPhaseCreated {
return m, nil
}
}
}
return MemberStatus{}, maskAny(errors.Wrap(NotFoundError, "No member available for removal"))
}
// MembersReady returns the number of members that are in the Ready state.
func (l MemberStatusList) MembersReady() int {
readyCount := 0
for _, x := range l {
if x.Conditions.IsTrue(ConditionTypeReady) {
readyCount++
}
}
return readyCount
}
// AllMembersReady returns the true if all members are in the Ready state.
func (l MemberStatusList) AllMembersReady() bool {
return len(l) == l.MembersReady()
}
// AllConditionTrueSince returns true if all members satisfy the condition since the given period
func (l MemberStatusList) AllConditionTrueSince(cond ConditionType, status v1.ConditionStatus, period time.Duration) bool {
for _, x := range l {
if c, ok := x.Conditions.Get(cond); ok {
if c.Status == status && c.LastTransitionTime.Time.Add(period).Before(time.Now()) {
continue
}
}
return false
}
return true
}
// AllFailed returns true if all members are failed
func (l MemberStatusList) AllFailed() bool {
for _, x := range l {
if !x.Phase.IsFailed() {
return false
}
}
return true
}

View file

@ -1,91 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"testing"
"github.com/stretchr/testify/assert"
)
// TestMemberStatusList tests modifying a MemberStatusList.
func TestMemberStatusList(t *testing.T) {
list := &MemberStatusList{}
m1 := MemberStatus{ID: "m1"}
m2 := MemberStatus{ID: "m2"}
m3 := MemberStatus{ID: "m3"}
assert.Equal(t, 0, len(*list))
assert.NoError(t, list.add(m1))
assert.Equal(t, 1, len(*list))
assert.NoError(t, list.add(m2))
assert.NoError(t, list.add(m3))
assert.Equal(t, 3, len(*list))
assert.Error(t, list.add(m2))
assert.Equal(t, 3, len(*list))
assert.NoError(t, list.removeByID(m3.ID))
assert.Equal(t, 2, len(*list))
assert.False(t, list.ContainsID(m3.ID))
assert.Equal(t, m1.ID, (*list)[0].ID)
assert.Equal(t, m2.ID, (*list)[1].ID)
m2.PodName = "foo"
assert.NoError(t, list.update(m2))
assert.Equal(t, 2, len(*list))
assert.True(t, list.ContainsID(m2.ID))
x, found := list.ElementByPodName("foo")
assert.True(t, found)
assert.Equal(t, "foo", x.PodName)
assert.Equal(t, m2.ID, x.ID)
assert.NoError(t, list.add(m3))
assert.Equal(t, 3, len(*list))
assert.Equal(t, m1.ID, (*list)[0].ID)
assert.Equal(t, m2.ID, (*list)[1].ID)
assert.Equal(t, m3.ID, (*list)[2].ID)
list2 := &MemberStatusList{m3, m2, m1}
assert.True(t, list.Equal(*list2))
assert.True(t, list2.Equal(*list))
list3 := &MemberStatusList{m3, m1}
assert.False(t, list.Equal(*list3))
assert.False(t, list3.Equal(*list))
list4 := MemberStatusList{m3, m2, m1}
list4[1].Phase = "something-else"
assert.False(t, list.Equal(list4))
assert.False(t, list4.Equal(*list))
m4 := MemberStatus{ID: "m4"}
list5 := &MemberStatusList{m1, m2, m4}
assert.False(t, list.Equal(*list5))
assert.False(t, list5.Equal(*list))
list6 := &MemberStatusList{m1, m2, m3, m4}
assert.False(t, list.Equal(*list6))
assert.False(t, list6.Equal(*list))
}

View file

@ -1,74 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// TestMemberStatusRecentTerminations tests the functions related to MemberStatus.RecentTerminations.
func TestMemberStatusRecentTerminations(t *testing.T) {
relTime := func(delta time.Duration) metav1.Time {
return metav1.Time{Time: time.Now().Add(delta)}
}
s := MemberStatus{}
assert.Equal(t, 0, s.RecentTerminationsSince(time.Now().Add(-time.Hour)))
assert.Equal(t, 0, s.RemoveTerminationsBefore(time.Now()))
s.RecentTerminations = []metav1.Time{metav1.Now()}
assert.Equal(t, 1, s.RecentTerminationsSince(time.Now().Add(-time.Minute)))
assert.Equal(t, 0, s.RecentTerminationsSince(time.Now().Add(time.Minute)))
assert.Equal(t, 0, s.RemoveTerminationsBefore(time.Now().Add(-time.Hour)))
s.RecentTerminations = []metav1.Time{relTime(-time.Hour), relTime(-time.Minute), relTime(time.Minute)}
assert.Equal(t, 3, s.RecentTerminationsSince(time.Now().Add(-time.Hour*2)))
assert.Equal(t, 2, s.RecentTerminationsSince(time.Now().Add(-time.Minute*2)))
assert.Equal(t, 2, s.RemoveTerminationsBefore(time.Now()))
assert.Len(t, s.RecentTerminations, 1)
}
// TestMemberStatusIsNotReadySince tests the functions related to MemberStatus.IsNotReadySince.
func TestMemberStatusIsNotReadySince(t *testing.T) {
s := MemberStatus{
CreatedAt: metav1.Now(),
}
assert.False(t, s.IsNotReadySince(time.Now().Add(-time.Hour)))
s.CreatedAt.Time = time.Now().Add(-time.Hour)
assert.False(t, s.IsNotReadySince(time.Now().Add(-2*time.Hour)))
assert.True(t, s.IsNotReadySince(time.Now().Add(-(time.Hour - time.Minute))))
s.CreatedAt = metav1.Now()
s.Conditions.Update(ConditionTypeReady, true, "", "")
assert.False(t, s.IsNotReadySince(time.Now().Add(-time.Minute)))
assert.False(t, s.IsNotReadySince(time.Now().Add(time.Minute)))
s.Conditions.Update(ConditionTypeReady, false, "", "")
assert.False(t, s.IsNotReadySince(time.Now().Add(-time.Minute)))
assert.True(t, s.IsNotReadySince(time.Now().Add(time.Minute)))
}

View file

@ -1,109 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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 v1alpha
import (
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
v1 "k8s.io/api/core/v1"
)
// MetricsAuthenticationSpec contains spec for authentication with arangodb
type MetricsAuthenticationSpec struct {
// JWTTokenSecretName contains the name of the JWT kubernetes secret used for authentication
JWTTokenSecretName *string `json:"jwtTokenSecretName,omitempty"`
}
// MetricsSpec contains spec for arangodb exporter
type MetricsSpec struct {
Enabled *bool `json:"enabled,omitempty"`
Image *string `json:"image,omitempty"`
Authentication MetricsAuthenticationSpec `json:"authentication,omitempty"`
Resources v1.ResourceRequirements `json:"resources,omitempty"`
}
// IsEnabled returns whether metrics are enabled or not
func (s *MetricsSpec) IsEnabled() bool {
return util.BoolOrDefault(s.Enabled, false)
}
// HasImage returns whether a image was specified or not
func (s *MetricsSpec) HasImage() bool {
return s.Image != nil
}
// GetImage returns the Image or empty string
func (s *MetricsSpec) GetImage() string {
return util.StringOrDefault(s.Image)
}
// SetDefaults sets default values
func (s *MetricsSpec) SetDefaults(defaultTokenName string, isAuthenticated bool) {
if s.Enabled == nil {
s.Enabled = util.NewBool(false)
}
if s.GetJWTTokenSecretName() == "" {
s.Authentication.JWTTokenSecretName = util.NewString(defaultTokenName)
}
}
// GetJWTTokenSecretName returns the token secret name or empty string
func (s *MetricsSpec) GetJWTTokenSecretName() string {
return util.StringOrDefault(s.Authentication.JWTTokenSecretName)
}
// HasJWTTokenSecretName returns true if a secret name was specified
func (s *MetricsSpec) HasJWTTokenSecretName() bool {
return s.Authentication.JWTTokenSecretName != nil
}
// SetDefaultsFrom fills unspecified fields with a value from given source spec.
func (s *MetricsSpec) SetDefaultsFrom(source MetricsSpec) {
if s.Enabled == nil {
s.Enabled = util.NewBoolOrNil(source.Enabled)
}
if s.Image == nil {
s.Image = util.NewStringOrNil(source.Image)
}
if s.Authentication.JWTTokenSecretName == nil {
s.Authentication.JWTTokenSecretName = util.NewStringOrNil(source.Authentication.JWTTokenSecretName)
}
setDefaultsFromResourceList(&s.Resources.Limits, source.Resources.Limits)
setDefaultsFromResourceList(&s.Resources.Requests, source.Resources.Requests)
}
// Validate the given spec
func (s *MetricsSpec) Validate() error {
if s.HasJWTTokenSecretName() {
if err := k8sutil.ValidateResourceName(s.GetJWTTokenSecretName()); err != nil {
return err
}
}
return nil
}
// ResetImmutableFields replaces all immutable fields in the given target with values from the source spec.
func (s MetricsSpec) ResetImmutableFields(fieldPrefix string, target *MetricsSpec) []string {
return nil
}

View file

@ -1,62 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
)
// MonitoringSpec holds monitoring specific configuration settings
type MonitoringSpec struct {
TokenSecretName *string `json:"tokenSecretName,omitempty"`
}
// GetTokenSecretName returns the value of tokenSecretName.
func (s MonitoringSpec) GetTokenSecretName() string {
return util.StringOrDefault(s.TokenSecretName)
}
// Validate the given spec
func (s MonitoringSpec) Validate() error {
if err := k8sutil.ValidateOptionalResourceName(s.GetTokenSecretName()); err != nil {
return maskAny(err)
}
return nil
}
// SetDefaults fills in missing defaults
func (s *MonitoringSpec) SetDefaults(defaultTokenSecretName string) {
if s.GetTokenSecretName() == "" {
// Note that we don't check for nil here, since even a specified, but empty
// string should result in the default value.
s.TokenSecretName = util.NewString(defaultTokenSecretName)
}
}
// SetDefaultsFrom fills unspecified fields with a value from given source spec.
func (s *MonitoringSpec) SetDefaultsFrom(source MonitoringSpec) {
if s.TokenSecretName == nil {
s.TokenSecretName = util.NewStringOrNil(source.TokenSecretName)
}
}

View file

@ -1,56 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"testing"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/stretchr/testify/assert"
)
func TestMonitoringSpecValidate(t *testing.T) {
// Valid
assert.Nil(t, MonitoringSpec{TokenSecretName: nil}.Validate())
assert.Nil(t, MonitoringSpec{TokenSecretName: util.NewString("")}.Validate())
assert.Nil(t, MonitoringSpec{TokenSecretName: util.NewString("foo")}.Validate())
assert.Nil(t, MonitoringSpec{TokenSecretName: util.NewString("foo")}.Validate())
// Not valid
assert.Error(t, MonitoringSpec{TokenSecretName: util.NewString("Foo")}.Validate())
}
func TestMonitoringSpecSetDefaults(t *testing.T) {
def := func(spec MonitoringSpec) MonitoringSpec {
spec.SetDefaults("")
return spec
}
def2 := func(spec MonitoringSpec) MonitoringSpec {
spec.SetDefaults("def2")
return spec
}
assert.Equal(t, "", def(MonitoringSpec{}).GetTokenSecretName())
assert.Equal(t, "def2", def2(MonitoringSpec{}).GetTokenSecretName())
assert.Equal(t, "foo", def(MonitoringSpec{TokenSecretName: util.NewString("foo")}).GetTokenSecretName())
}

View file

@ -1,62 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"github.com/pkg/errors"
)
// Percent is a percentage between 0 and 100.
type Percent int
// Validate the given percentage.
func (p Percent) Validate() error {
if p < 0 || p > 100 {
return maskAny(errors.Wrapf(ValidationError, "Percentage must be between 0 and 100, got %d", int(p)))
}
return nil
}
// NewPercent returns a reference to a percent with given value.
func NewPercent(input Percent) *Percent {
return &input
}
// NewPercentOrNil returns nil if input is nil, otherwise returns a clone of the given value.
func NewPercentOrNil(input *Percent) *Percent {
if input == nil {
return nil
}
return NewPercent(*input)
}
// PercentOrDefault returns the default value or 0 if input is nil, otherwise returns the referenced value.
func PercentOrDefault(input *Percent, defaultValue ...Percent) Percent {
if input == nil {
if len(defaultValue) > 0 {
return defaultValue[0]
}
return 0
}
return *input
}

View file

@ -1,145 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/dchest/uniuri"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// ActionType is a strongly typed name for a plan action item
type ActionType string
const (
// ActionTypeAddMember causes a member to be added.
ActionTypeAddMember ActionType = "AddMember"
// ActionTypeRemoveMember causes a member to be removed.
ActionTypeRemoveMember ActionType = "RemoveMember"
// ActionTypeCleanOutMember causes a member to be cleaned out (dbserver only).
ActionTypeCleanOutMember ActionType = "CleanOutMember"
// ActionTypeShutdownMember causes a member to be shutdown and removed from the cluster.
ActionTypeShutdownMember ActionType = "ShutdownMember"
// ActionTypeRotateMember causes a member to be shutdown and have it's pod removed.
ActionTypeRotateMember ActionType = "RotateMember"
// ActionTypeUpgradeMember causes a member to be shutdown and have it's pod removed, restarted with AutoUpgrade option, waited until termination and the restarted again.
ActionTypeUpgradeMember ActionType = "UpgradeMember"
// ActionTypeWaitForMemberUp causes the plan to wait until the member is considered "up".
ActionTypeWaitForMemberUp ActionType = "WaitForMemberUp"
// ActionTypeRenewTLSCertificate causes the TLS certificate of a member to be renewed.
ActionTypeRenewTLSCertificate ActionType = "RenewTLSCertificate"
// ActionTypeRenewTLSCACertificate causes the TLS CA certificate of the entire deployment to be renewed.
ActionTypeRenewTLSCACertificate ActionType = "RenewTLSCACertificate"
// ActionTypeSetCurrentImage causes status.CurrentImage to be updated to the image given in the action.
ActionTypeSetCurrentImage ActionType = "SetCurrentImage"
// ActionTypeDisableClusterScaling turns off scaling DBservers and coordinators
ActionTypeDisableClusterScaling ActionType = "ScalingDisabled"
// ActionTypeEnableClusterScaling turns on scaling DBservers and coordinators
ActionTypeEnableClusterScaling ActionType = "ScalingEnabled"
)
const (
// MemberIDPreviousAction is used for Action.MemberID when the MemberID
// should be derived from the previous action.
MemberIDPreviousAction = "@previous"
)
// Action represents a single action to be taken to update a deployment.
type Action struct {
// ID of this action (unique for every action)
ID string `json:"id"`
// Type of action.
Type ActionType `json:"type"`
// ID reference of the member involved in this action (if any)
MemberID string `json:"memberID,omitempty"`
// Group involved in this action
Group ServerGroup `json:"group,omitempty"`
// CreationTime is set the when the action is created.
CreationTime metav1.Time `json:"creationTime"`
// StartTime is set the when the action has been started, but needs to wait to be finished.
StartTime *metav1.Time `json:"startTime,omitempty"`
// Reason for this action
Reason string `json:"reason,omitempty"`
// Image used in can of a SetCurrentImage action.
Image string `json:"image,omitempty"`
}
// Equal compares two Actions
func (a Action) Equal(other Action) bool {
return a.ID == other.ID &&
a.Type == other.Type &&
a.MemberID == other.MemberID &&
a.Group == other.Group &&
util.TimeCompareEqual(a.CreationTime, other.CreationTime) &&
util.TimeCompareEqualPointer(a.StartTime, other.StartTime) &&
a.Reason == other.Reason &&
a.Image == other.Image
}
// NewAction instantiates a new Action.
func NewAction(actionType ActionType, group ServerGroup, memberID string, reason ...string) Action {
a := Action{
ID: uniuri.New(),
Type: actionType,
MemberID: memberID,
Group: group,
CreationTime: metav1.Now(),
}
if len(reason) != 0 {
a.Reason = reason[0]
}
return a
}
// SetImage sets the Image field to the given value and returns the modified
// action.
func (a Action) SetImage(image string) Action {
a.Image = image
return a
}
// Plan is a list of actions that will be taken to update a deployment.
// Only 1 action is in progress at a time. The operator will wait for that
// action to be completely and then remove the action.
type Plan []Action
// Equal compares two Plan
func (p Plan) Equal(other Plan) bool {
// For plan the order is relevant!
if len(p) != len(other) {
return false
}
for i := 0; i < len(p); i++ {
if !p[i].Equal(other[i]) {
return false
}
}
return true
}
// IsEmpty checks if plan is empty
func (p Plan) IsEmpty() bool {
return len(p) == 0
}

View file

@ -1,56 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"github.com/arangodb/kube-arangodb/pkg/apis/deployment"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
const (
ArangoDeploymentVersion = "v1alpha"
)
var (
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
AddToScheme = SchemeBuilder.AddToScheme
SchemeGroupVersion = schema.GroupVersion{Group: deployment.ArangoDeploymentGroupName, Version: ArangoDeploymentVersion}
)
// Resource gets an ArangoCluster GroupResource for a specified resource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
// addKnownTypes adds the set of types defined in this package to the supplied scheme.
func addKnownTypes(s *runtime.Scheme) error {
s.AddKnownTypes(SchemeGroupVersion,
&ArangoDeployment{},
&ArangoDeploymentList{},
)
metav1.AddToGroupVersion(s, SchemeGroupVersion)
return nil
}

View file

@ -1,88 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
)
// RocksDBEncryptionSpec holds rocksdb encryption at rest specific configuration settings
type RocksDBEncryptionSpec struct {
KeySecretName *string `json:"keySecretName,omitempty"`
}
// GetKeySecretName returns the value of keySecretName.
func (s RocksDBEncryptionSpec) GetKeySecretName() string {
return util.StringOrDefault(s.KeySecretName)
}
// IsEncrypted returns true when an encryption key secret name is provided,
// false otherwise.
func (s RocksDBEncryptionSpec) IsEncrypted() bool {
return s.GetKeySecretName() != ""
}
// RocksDBSpec holds rocksdb specific configuration settings
type RocksDBSpec struct {
Encryption RocksDBEncryptionSpec `json:"encryption"`
}
// IsEncrypted returns true when an encryption key secret name is provided,
// false otherwise.
func (s RocksDBSpec) IsEncrypted() bool {
return s.Encryption.IsEncrypted()
}
// Validate the given spec
func (s RocksDBSpec) Validate() error {
if err := k8sutil.ValidateOptionalResourceName(s.Encryption.GetKeySecretName()); err != nil {
return maskAny(err)
}
return nil
}
// SetDefaults fills in missing defaults
func (s *RocksDBSpec) SetDefaults() {
// Nothing needed
}
// SetDefaultsFrom fills unspecified fields with a value from given source spec.
func (s *RocksDBSpec) SetDefaultsFrom(source RocksDBSpec) {
if s.Encryption.KeySecretName == nil {
s.Encryption.KeySecretName = util.NewStringOrNil(source.Encryption.KeySecretName)
}
}
// ResetImmutableFields replaces all immutable fields in the given target with values from the source spec.
// It returns a list of fields that have been reset.
// Field names are relative to given field prefix.
func (s RocksDBSpec) ResetImmutableFields(fieldPrefix string, target *RocksDBSpec) []string {
var resetFields []string
if s.IsEncrypted() != target.IsEncrypted() {
// Note: You can change the name, but not from empty to non-empty (or reverse).
target.Encryption.KeySecretName = util.NewStringOrNil(s.Encryption.KeySecretName)
resetFields = append(resetFields, fieldPrefix+".encryption.keySecretName")
}
return resetFields
}

View file

@ -1,97 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"testing"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/stretchr/testify/assert"
)
func TestRocksDBSpecValidate(t *testing.T) {
// Valid
assert.Nil(t, RocksDBSpec{}.Validate())
assert.Nil(t, RocksDBSpec{Encryption: RocksDBEncryptionSpec{KeySecretName: util.NewString("foo")}}.Validate())
// Not valid
assert.Error(t, RocksDBSpec{Encryption: RocksDBEncryptionSpec{KeySecretName: util.NewString("Foo")}}.Validate())
}
func TestRocksDBSpecIsEncrypted(t *testing.T) {
assert.False(t, RocksDBSpec{}.IsEncrypted())
assert.False(t, RocksDBSpec{Encryption: RocksDBEncryptionSpec{KeySecretName: util.NewString("")}}.IsEncrypted())
assert.True(t, RocksDBSpec{Encryption: RocksDBEncryptionSpec{KeySecretName: util.NewString("foo")}}.IsEncrypted())
}
func TestRocksDBSpecSetDefaults(t *testing.T) {
def := func(spec RocksDBSpec) RocksDBSpec {
spec.SetDefaults()
return spec
}
assert.Equal(t, "", def(RocksDBSpec{}).Encryption.GetKeySecretName())
}
func TestRocksDBSpecResetImmutableFields(t *testing.T) {
tests := []struct {
Original RocksDBSpec
Target RocksDBSpec
Expected RocksDBSpec
Result []string
}{
// Valid "changes"
{
RocksDBSpec{},
RocksDBSpec{},
RocksDBSpec{},
nil,
},
{
RocksDBSpec{Encryption: RocksDBEncryptionSpec{KeySecretName: util.NewString("foo")}},
RocksDBSpec{Encryption: RocksDBEncryptionSpec{KeySecretName: util.NewString("foo")}},
RocksDBSpec{Encryption: RocksDBEncryptionSpec{KeySecretName: util.NewString("foo")}},
nil,
},
{
RocksDBSpec{Encryption: RocksDBEncryptionSpec{KeySecretName: util.NewString("foo")}},
RocksDBSpec{Encryption: RocksDBEncryptionSpec{KeySecretName: util.NewString("foo2")}},
RocksDBSpec{Encryption: RocksDBEncryptionSpec{KeySecretName: util.NewString("foo2")}},
nil,
},
// Invalid changes
{
RocksDBSpec{Encryption: RocksDBEncryptionSpec{KeySecretName: util.NewString("foo")}},
RocksDBSpec{Encryption: RocksDBEncryptionSpec{KeySecretName: util.NewString("")}},
RocksDBSpec{Encryption: RocksDBEncryptionSpec{KeySecretName: util.NewString("foo")}},
[]string{"test.encryption.keySecretName"},
},
}
for _, test := range tests {
result := test.Original.ResetImmutableFields("test", &test.Target)
assert.Equal(t, test.Result, result)
assert.Equal(t, test.Expected, test.Target)
}
}

View file

@ -1,88 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
// SecretHashes keeps track of the value of secrets
// so we can detect changes.
// For each used secret, a sha256 hash is stored.
type SecretHashes struct {
// AuthJWT contains the hash of the auth.jwtSecretName secret
AuthJWT string `json:"auth-jwt,omitempty"`
// RocksDBEncryptionKey contains the hash of the rocksdb.encryption.keySecretName secret
RocksDBEncryptionKey string `json:"rocksdb-encryption-key,omitempty"`
// TLSCA contains the hash of the tls.caSecretName secret
TLSCA string `json:"tls-ca,omitempty"`
// SyncTLSCA contains the hash of the sync.tls.caSecretName secret
SyncTLSCA string `json:"sync-tls-ca,omitempty"`
// User's map contains hashes for each user
Users map[string]string `json:"users,omitempty"`
}
// Equal compares two SecretHashes
func (sh *SecretHashes) Equal(other *SecretHashes) bool {
if sh == nil || other == nil {
return false
} else if sh == other {
return true
}
return sh.AuthJWT == other.AuthJWT &&
sh.RocksDBEncryptionKey == other.RocksDBEncryptionKey &&
sh.TLSCA == other.TLSCA &&
sh.SyncTLSCA == other.SyncTLSCA &&
isStringMapEqual(sh.Users, other.Users)
}
// NewEmptySecretHashes creates new empty structure
func NewEmptySecretHashes() *SecretHashes {
sh := &SecretHashes{}
sh.Users = make(map[string]string)
return sh
}
func isStringMapEqual(first map[string]string, second map[string]string) bool {
if first == nil && second == nil {
return true
}
if first == nil || second == nil {
return false
}
if len(first) != len(second) {
return false
}
for key, valueF := range first {
valueS, ok := second[key]
if !ok {
return false
}
if valueF != valueS {
return false
}
}
return true
}

View file

@ -1,164 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2019 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
//
// Author tomasz@arangodb.con
//
package v1alpha
import (
"github.com/magiconair/properties/assert"
"testing"
)
func TestSecretHashes_Equal(t *testing.T) {
// Arrange
sh := SecretHashes{}
testCases := []struct {
Name string
CompareFrom *SecretHashes
CompareTo *SecretHashes
Expected bool
}{
{
Name: "Parameter can not be nil",
CompareFrom: &SecretHashes{},
Expected: false,
},
{
Name: "The addresses are the same",
CompareFrom: &sh,
CompareTo: &sh,
Expected: true,
},
{
Name: "JWT token is different",
CompareFrom: &SecretHashes{
AuthJWT: "1",
},
CompareTo: &SecretHashes{
AuthJWT: "2",
},
Expected: false,
},
{
Name: "Users are different",
CompareFrom: &SecretHashes{
Users: map[string]string{
"root": "",
},
},
CompareTo: &SecretHashes{},
Expected: false,
},
{
Name: "User's table size is different",
CompareFrom: &SecretHashes{
Users: map[string]string{
"root": "",
},
},
CompareTo: &SecretHashes{
Users: map[string]string{
"root": "",
"user": "",
},
},
Expected: false,
},
{
Name: "User's table has got different users",
CompareFrom: &SecretHashes{
Users: map[string]string{
"root": "",
},
},
CompareTo: &SecretHashes{
Users: map[string]string{
"user": "",
},
},
Expected: false,
},
{
Name: "User's table has got different hashes for users",
CompareFrom: &SecretHashes{
Users: map[string]string{
"root": "123",
},
},
CompareTo: &SecretHashes{
Users: map[string]string{
"root": "1234",
},
},
Expected: false,
},
{
Name: "Secret hashes are the same",
CompareFrom: &SecretHashes{
AuthJWT: "1",
RocksDBEncryptionKey: "2",
TLSCA: "3",
SyncTLSCA: "4",
Users: map[string]string{
"root": "123",
},
},
CompareTo: &SecretHashes{
AuthJWT: "1",
RocksDBEncryptionKey: "2",
TLSCA: "3",
SyncTLSCA: "4",
Users: map[string]string{
"root": "123",
},
},
Expected: true,
},
{
Name: "Secret hashes are the same without users",
CompareFrom: &SecretHashes{
AuthJWT: "1",
RocksDBEncryptionKey: "2",
TLSCA: "3",
SyncTLSCA: "4",
},
CompareTo: &SecretHashes{
AuthJWT: "1",
RocksDBEncryptionKey: "2",
TLSCA: "3",
SyncTLSCA: "4",
},
Expected: true,
},
}
for _, testCase := range testCases {
//nolint:scopelint
t.Run(testCase.Name, func(t *testing.T) {
// Act
expected := testCase.CompareFrom.Equal(testCase.CompareTo)
// Assert
assert.Equal(t, testCase.Expected, expected)
})
}
}

View file

@ -1,197 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import time "time"
type ServerGroup int
const (
ServerGroupUnknown ServerGroup = 0
ServerGroupSingle ServerGroup = 1
ServerGroupAgents ServerGroup = 2
ServerGroupDBServers ServerGroup = 3
ServerGroupCoordinators ServerGroup = 4
ServerGroupSyncMasters ServerGroup = 5
ServerGroupSyncWorkers ServerGroup = 6
ServerGroupSingleString = "single"
ServerGroupAgentsString = "agent"
ServerGroupDBServersString = "dbserver"
ServerGroupCoordinatorsString = "coordinator"
ServerGroupSyncMastersString = "syncmaster"
ServerGroupSyncWorkersString = "syncworker"
ServerGroupSingleAbbreviatedString = "sngl"
ServerGroupAgentsAbbreviatedString = "agnt"
ServerGroupDBServersAbbreviatedString = "prmr"
ServerGroupCoordinatorsAbbreviatedString = "crdn"
ServerGroupSyncMastersAbbreviatedString = "syma"
ServerGroupSyncWorkersAbbreviatedString = "sywo"
)
var (
// AllServerGroups contains a constant list of all known server groups
AllServerGroups = []ServerGroup{
ServerGroupSingle,
ServerGroupAgents,
ServerGroupDBServers,
ServerGroupCoordinators,
ServerGroupSyncMasters,
ServerGroupSyncWorkers,
}
)
// AsRole returns the "role" value for the given group.
func (g ServerGroup) AsRole() string {
switch g {
case ServerGroupSingle:
return ServerGroupSingleString
case ServerGroupAgents:
return ServerGroupAgentsString
case ServerGroupDBServers:
return ServerGroupDBServersString
case ServerGroupCoordinators:
return ServerGroupCoordinatorsString
case ServerGroupSyncMasters:
return ServerGroupSyncMastersString
case ServerGroupSyncWorkers:
return ServerGroupSyncWorkersString
default:
return "?"
}
}
// AsRoleAbbreviated returns the abbreviation of the "role" value for the given group.
func (g ServerGroup) AsRoleAbbreviated() string {
switch g {
case ServerGroupSingle:
return ServerGroupSingleAbbreviatedString
case ServerGroupAgents:
return ServerGroupAgentsAbbreviatedString
case ServerGroupDBServers:
return ServerGroupDBServersAbbreviatedString
case ServerGroupCoordinators:
return ServerGroupCoordinatorsAbbreviatedString
case ServerGroupSyncMasters:
return ServerGroupSyncMastersAbbreviatedString
case ServerGroupSyncWorkers:
return ServerGroupSyncWorkersAbbreviatedString
default:
return "?"
}
}
// DefaultTerminationGracePeriod returns the default period between SIGTERM & SIGKILL for a server in the given group.
func (g ServerGroup) DefaultTerminationGracePeriod() time.Duration {
switch g {
case ServerGroupSingle:
return time.Minute
case ServerGroupAgents:
return time.Minute
case ServerGroupDBServers:
return time.Hour
default:
return time.Second * 30
}
}
// IsStateless returns true when the groups runs servers without a persistent volume.
func (g ServerGroup) IsStateless() bool {
switch g {
case ServerGroupCoordinators, ServerGroupSyncMasters, ServerGroupSyncWorkers:
return true
default:
return false
}
}
// IsArangod returns true when the groups runs servers of type `arangod`.
func (g ServerGroup) IsArangod() bool {
switch g {
case ServerGroupSingle, ServerGroupAgents, ServerGroupDBServers, ServerGroupCoordinators:
return true
default:
return false
}
}
// IsArangosync returns true when the groups runs servers of type `arangosync`.
func (g ServerGroup) IsArangosync() bool {
switch g {
case ServerGroupSyncMasters, ServerGroupSyncWorkers:
return true
default:
return false
}
}
// IsExportMetrics return true when the group can be used with the arangodbexporter
func (g ServerGroup) IsExportMetrics() bool {
switch g {
case ServerGroupCoordinators, ServerGroupDBServers, ServerGroupSingle:
return true
default:
return false
}
}
// ServerGroupFromAbbreviatedRole returns ServerGroup from abbreviated role
func ServerGroupFromAbbreviatedRole(label string) ServerGroup {
switch label {
case ServerGroupSingleAbbreviatedString:
return ServerGroupSingle
case ServerGroupAgentsAbbreviatedString:
return ServerGroupAgents
case ServerGroupDBServersAbbreviatedString:
return ServerGroupDBServers
case ServerGroupCoordinatorsAbbreviatedString:
return ServerGroupCoordinators
case ServerGroupSyncMastersAbbreviatedString:
return ServerGroupSyncMasters
case ServerGroupSyncWorkersAbbreviatedString:
return ServerGroupSyncWorkers
default:
return ServerGroupUnknown
}
}
// ServerGroupFromAbbreviatedRole returns ServerGroup from role
func ServerGroupFromRole(label string) ServerGroup {
switch label {
case ServerGroupSingleString:
return ServerGroupSingle
case ServerGroupAgentsString:
return ServerGroupAgents
case ServerGroupDBServersString:
return ServerGroupDBServers
case ServerGroupCoordinatorsString:
return ServerGroupCoordinators
case ServerGroupSyncMastersString:
return ServerGroupSyncMasters
case ServerGroupSyncWorkersString:
return ServerGroupSyncWorkers
default:
return ServerGroupUnknown
}
}

View file

@ -1,351 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"math"
"strings"
"github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"github.com/arangodb/kube-arangodb/pkg/util"
arangod_options "github.com/arangodb/kube-arangodb/pkg/util/arangod/options"
arangosync_options "github.com/arangodb/kube-arangodb/pkg/util/arangosync/options"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
)
// ServerGroupSpec contains the specification for all servers in a specific group (e.g. all agents)
type ServerGroupSpec struct {
// Count holds the requested number of servers
Count *int `json:"count,omitempty"`
// MinCount specifies a lower limit for count
MinCount *int `json:"minCount,omitempty"`
// MaxCount specifies a upper limit for count
MaxCount *int `json:"maxCount,omitempty"`
// Args holds additional commandline arguments
Args []string `json:"args,omitempty"`
// StorageClassName specifies the classname for storage of the servers.
StorageClassName *string `json:"storageClassName,omitempty"`
// Resources holds resource requests & limits
Resources v1.ResourceRequirements `json:"resources,omitempty"`
// Tolerations specifies the tolerations added to Pods in this group.
Tolerations []v1.Toleration `json:"tolerations,omitempty"`
// Annotations specified the annotations added to Pods in this group.
Annotations map[string]string `json:"annotations,omitempty"`
// ServiceAccountName specifies the name of the service account used for Pods in this group.
ServiceAccountName *string `json:"serviceAccountName,omitempty"`
// NodeSelector speficies a set of selectors for nodes
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
// Probes specifies additional behaviour for probes
Probes *ServerGroupProbesSpec `json:"probes,omitempty"`
// PriorityClassName specifies a priority class name
PriorityClassName string `json:"priorityClassName,omitempty"`
// VolumeClaimTemplate specifies a template for volume claims
VolumeClaimTemplate *v1.PersistentVolumeClaim `json:"volumeClaimTemplate,omitempty"`
// Sidecars specifies a list of additional containers to be started
Sidecars []v1.Container `json:"sidecars,omitempty"`
}
// ServerGroupProbesSpec contains specification for probes for pods of the server group
type ServerGroupProbesSpec struct {
// LivenessProbeDisabled if true livenessProbes are disabled
LivenessProbeDisabled *bool `json:"livenessProbeDisabled,omitempty"`
// LivenessProbeDisabled if specified the given probes is used as liveness probe
//LivenessProbeOverride *v1.Probe `json:"LivenessProbeOverride,omitempty"`
// LivenessProbeDisabled if true readinessProbes are disabled
ReadinessProbeDisabled *bool `json:"ReadinessProbeDisabled,omitempty"`
// ReadinessProbeOverride if specified the given probes is used as readiness probe
//ReadinessProbeOverride *v1.Probe `json:"ReadinessProbeOverride,omitempty"`
}
// // HasLivenessProbeOverride returns true if a livenessprobe override is set
// func (s ServerGroupProbesSpec) HasLivenessProbeOverride() bool {
// return s.LivenessProbeOverride != nil
// }
// // HasReadinessProbeOverride returns true if a readinessprobe override is set
// func (s ServerGroupProbesSpec) HasReadinessProbeOverride() bool {
// return s.ReadinessProbeOverride != nil
// }
// GetSidecars returns a list of sidecars the use wish to add
func (s ServerGroupSpec) GetSidecars() []v1.Container {
return s.Sidecars
}
// IsLivenessProbeDisabled returns true if liveness probes are disabled
func (s ServerGroupProbesSpec) IsLivenessProbeDisabled() bool {
return util.BoolOrDefault(s.LivenessProbeDisabled)
}
// IsReadinessProbeDisabled returns true if readiness probes are disabled
func (s ServerGroupProbesSpec) IsReadinessProbeDisabled() bool {
return util.BoolOrDefault(s.ReadinessProbeDisabled)
}
// HasVolumeClaimTemplate returns whether there is a volumeClaimTemplate or not
func (s ServerGroupSpec) HasVolumeClaimTemplate() bool {
return s.VolumeClaimTemplate != nil
}
// GetVolumeClaimTemplate returns a pointer to a volume claim template or nil if none is specified
func (s ServerGroupSpec) GetVolumeClaimTemplate() *v1.PersistentVolumeClaim {
return s.VolumeClaimTemplate
}
// GetCount returns the value of count.
func (s ServerGroupSpec) GetCount() int {
return util.IntOrDefault(s.Count)
}
// GetMinCount returns MinCount or 1 if not set
func (s ServerGroupSpec) GetMinCount() int {
return util.IntOrDefault(s.MinCount, 1)
}
// GetMaxCount returns MaxCount or
func (s ServerGroupSpec) GetMaxCount() int {
return util.IntOrDefault(s.MaxCount, math.MaxInt32)
}
// GetNodeSelector returns the selectors for nodes of this group
func (s ServerGroupSpec) GetNodeSelector() map[string]string {
return s.NodeSelector
}
// GetAnnotations returns the annotations of this group
func (s ServerGroupSpec) GetAnnotations() map[string]string {
return s.Annotations
}
// GetArgs returns the value of args.
func (s ServerGroupSpec) GetArgs() []string {
return s.Args
}
// GetStorageClassName returns the value of storageClassName.
func (s ServerGroupSpec) GetStorageClassName() string {
if pvc := s.GetVolumeClaimTemplate(); pvc != nil {
return util.StringOrDefault(pvc.Spec.StorageClassName)
}
return util.StringOrDefault(s.StorageClassName)
}
// GetTolerations returns the value of tolerations.
func (s ServerGroupSpec) GetTolerations() []v1.Toleration {
return s.Tolerations
}
// GetServiceAccountName returns the value of serviceAccountName.
func (s ServerGroupSpec) GetServiceAccountName() string {
return util.StringOrDefault(s.ServiceAccountName)
}
// HasProbesSpec returns true if Probes is non nil
func (s ServerGroupSpec) HasProbesSpec() bool {
return s.Probes != nil
}
// GetProbesSpec returns the Probes spec or the nil value if not set
func (s ServerGroupSpec) GetProbesSpec() ServerGroupProbesSpec {
if s.HasProbesSpec() {
return *s.Probes
}
return ServerGroupProbesSpec{}
}
// Validate the given group spec
func (s ServerGroupSpec) Validate(group ServerGroup, used bool, mode DeploymentMode, env Environment) error {
if used {
minCount := 1
if env == EnvironmentProduction {
// Set validation boundaries for production mode
switch group {
case ServerGroupSingle:
if mode == DeploymentModeActiveFailover {
minCount = 2
}
case ServerGroupAgents:
minCount = 3
case ServerGroupDBServers, ServerGroupCoordinators, ServerGroupSyncMasters, ServerGroupSyncWorkers:
minCount = 2
}
} else {
// Set validation boundaries for development mode
switch group {
case ServerGroupSingle:
if mode == DeploymentModeActiveFailover {
minCount = 2
}
case ServerGroupDBServers:
minCount = 2
}
}
if s.GetMinCount() > s.GetMaxCount() {
return maskAny(errors.Wrapf(ValidationError, "Invalid min/maxCount. Min (%d) bigger than Max (%d)", s.GetMinCount(), s.GetMaxCount()))
}
if s.GetCount() < s.GetMinCount() {
return maskAny(errors.Wrapf(ValidationError, "Invalid count value %d. Expected >= %d", s.GetCount(), s.GetMinCount()))
}
if s.GetCount() > s.GetMaxCount() {
return maskAny(errors.Wrapf(ValidationError, "Invalid count value %d. Expected <= %d", s.GetCount(), s.GetMaxCount()))
}
if s.GetCount() < minCount {
return maskAny(errors.Wrapf(ValidationError, "Invalid count value %d. Expected >= %d (implicit minimum; by deployment mode)", s.GetCount(), minCount))
}
if s.GetCount() > 1 && group == ServerGroupSingle && mode == DeploymentModeSingle {
return maskAny(errors.Wrapf(ValidationError, "Invalid count value %d. Expected 1", s.GetCount()))
}
if name := s.GetServiceAccountName(); name != "" {
if err := k8sutil.ValidateOptionalResourceName(name); err != nil {
return maskAny(errors.Wrapf(ValidationError, "Invalid serviceAccountName: %s", err))
}
}
if name := s.GetStorageClassName(); name != "" {
if err := k8sutil.ValidateOptionalResourceName(name); err != nil {
return maskAny(errors.Wrapf(ValidationError, "Invalid storageClassName: %s", err))
}
}
for _, arg := range s.Args {
parts := strings.Split(arg, "=")
optionKey := strings.TrimSpace(parts[0])
if group.IsArangod() {
if arangod_options.IsCriticalOption(optionKey) {
return maskAny(errors.Wrapf(ValidationError, "Critical option '%s' cannot be overriden", optionKey))
}
} else if group.IsArangosync() {
if arangosync_options.IsCriticalOption(optionKey) {
return maskAny(errors.Wrapf(ValidationError, "Critical option '%s' cannot be overriden", optionKey))
}
}
}
} else if s.GetCount() != 0 {
return maskAny(errors.Wrapf(ValidationError, "Invalid count value %d for un-used group. Expected 0", s.GetCount()))
}
return nil
}
// SetDefaults fills in missing defaults
func (s *ServerGroupSpec) SetDefaults(group ServerGroup, used bool, mode DeploymentMode) {
if s.GetCount() == 0 && used {
switch group {
case ServerGroupSingle:
if mode == DeploymentModeSingle {
s.Count = util.NewInt(1) // Single server
} else {
s.Count = util.NewInt(2) // ActiveFailover
}
default:
s.Count = util.NewInt(3)
}
} else if s.GetCount() > 0 && !used {
s.Count = nil
s.MinCount = nil
s.MaxCount = nil
}
if !s.HasVolumeClaimTemplate() {
if _, found := s.Resources.Requests[v1.ResourceStorage]; !found {
switch group {
case ServerGroupSingle, ServerGroupAgents, ServerGroupDBServers:
volumeMode := v1.PersistentVolumeFilesystem
s.VolumeClaimTemplate = &v1.PersistentVolumeClaim{
Spec: v1.PersistentVolumeClaimSpec{
AccessModes: []v1.PersistentVolumeAccessMode{
v1.ReadWriteOnce,
},
VolumeMode: &volumeMode,
Resources: v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceStorage: resource.MustParse("8Gi"),
},
},
},
}
}
}
}
}
// setDefaultsFromResourceList fills unspecified fields with a value from given source spec.
func setDefaultsFromResourceList(s *v1.ResourceList, source v1.ResourceList) {
for k, v := range source {
if *s == nil {
*s = make(v1.ResourceList)
}
if _, found := (*s)[k]; !found {
(*s)[k] = v
}
}
}
// SetDefaultsFrom fills unspecified fields with a value from given source spec.
func (s *ServerGroupSpec) SetDefaultsFrom(source ServerGroupSpec) {
if s.Count == nil {
s.Count = util.NewIntOrNil(source.Count)
}
if s.MinCount == nil {
s.MinCount = util.NewIntOrNil(source.MinCount)
}
if s.MaxCount == nil {
s.MaxCount = util.NewIntOrNil(source.MaxCount)
}
if s.Args == nil {
s.Args = source.Args
}
if s.StorageClassName == nil {
s.StorageClassName = util.NewStringOrNil(source.StorageClassName)
}
if s.Tolerations == nil {
s.Tolerations = source.Tolerations
}
if s.ServiceAccountName == nil {
s.ServiceAccountName = util.NewStringOrNil(source.ServiceAccountName)
}
if s.NodeSelector == nil {
s.NodeSelector = source.NodeSelector
}
setDefaultsFromResourceList(&s.Resources.Limits, source.Resources.Limits)
setDefaultsFromResourceList(&s.Resources.Requests, source.Resources.Requests)
if s.VolumeClaimTemplate == nil {
s.VolumeClaimTemplate = source.VolumeClaimTemplate.DeepCopy()
}
}
// ResetImmutableFields replaces all immutable fields in the given target with values from the source spec.
// It returns a list of fields that have been reset.
func (s ServerGroupSpec) ResetImmutableFields(group ServerGroup, fieldPrefix string, target *ServerGroupSpec) []string {
var resetFields []string
if group == ServerGroupAgents {
if s.GetCount() != target.GetCount() {
target.Count = util.NewIntOrNil(s.Count)
resetFields = append(resetFields, fieldPrefix+".count")
}
}
if s.HasVolumeClaimTemplate() != target.HasVolumeClaimTemplate() {
target.VolumeClaimTemplate = s.GetVolumeClaimTemplate()
resetFields = append(resetFields, fieldPrefix+".volumeClaimTemplate")
}
return resetFields
}

View file

@ -1,133 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"testing"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/stretchr/testify/assert"
)
func TestServerGroupSpecValidateCount(t *testing.T) {
// Valid
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(1)}.Validate(ServerGroupSingle, true, DeploymentModeSingle, EnvironmentDevelopment))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(0)}.Validate(ServerGroupSingle, false, DeploymentModeCluster, EnvironmentDevelopment))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(1)}.Validate(ServerGroupAgents, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(3)}.Validate(ServerGroupAgents, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(1)}.Validate(ServerGroupAgents, true, DeploymentModeActiveFailover, EnvironmentDevelopment))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(3)}.Validate(ServerGroupAgents, true, DeploymentModeActiveFailover, EnvironmentDevelopment))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(2)}.Validate(ServerGroupDBServers, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(6)}.Validate(ServerGroupDBServers, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(1)}.Validate(ServerGroupCoordinators, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(2)}.Validate(ServerGroupCoordinators, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(3)}.Validate(ServerGroupAgents, true, DeploymentModeCluster, EnvironmentProduction))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(3)}.Validate(ServerGroupAgents, true, DeploymentModeActiveFailover, EnvironmentProduction))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(2)}.Validate(ServerGroupDBServers, true, DeploymentModeCluster, EnvironmentProduction))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(2)}.Validate(ServerGroupCoordinators, true, DeploymentModeCluster, EnvironmentProduction))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(2)}.Validate(ServerGroupSyncMasters, true, DeploymentModeCluster, EnvironmentProduction))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(2)}.Validate(ServerGroupSyncWorkers, true, DeploymentModeCluster, EnvironmentProduction))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(2), MinCount: util.NewInt(2), MaxCount: util.NewInt(5)}.Validate(ServerGroupCoordinators, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(1), MaxCount: util.NewInt(5)}.Validate(ServerGroupCoordinators, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(6), MinCount: util.NewInt(2)}.Validate(ServerGroupCoordinators, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(5), MinCount: util.NewInt(5), MaxCount: util.NewInt(5)}.Validate(ServerGroupCoordinators, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(2)}.Validate(ServerGroupCoordinators, true, DeploymentModeCluster, EnvironmentDevelopment))
// Invalid
assert.Error(t, ServerGroupSpec{Count: util.NewInt(1)}.Validate(ServerGroupSingle, false, DeploymentModeCluster, EnvironmentDevelopment))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(2)}.Validate(ServerGroupSingle, true, DeploymentModeSingle, EnvironmentDevelopment))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(1)}.Validate(ServerGroupSingle, true, DeploymentModeActiveFailover, EnvironmentProduction))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(0)}.Validate(ServerGroupAgents, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(0)}.Validate(ServerGroupAgents, true, DeploymentModeActiveFailover, EnvironmentDevelopment))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(0)}.Validate(ServerGroupDBServers, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(0)}.Validate(ServerGroupCoordinators, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(0)}.Validate(ServerGroupSyncMasters, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(0)}.Validate(ServerGroupSyncWorkers, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(-1)}.Validate(ServerGroupAgents, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(-1)}.Validate(ServerGroupAgents, true, DeploymentModeActiveFailover, EnvironmentDevelopment))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(-1)}.Validate(ServerGroupDBServers, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(-1)}.Validate(ServerGroupCoordinators, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(-1)}.Validate(ServerGroupSyncMasters, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(-1)}.Validate(ServerGroupSyncWorkers, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(2)}.Validate(ServerGroupAgents, true, DeploymentModeCluster, EnvironmentProduction))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(2)}.Validate(ServerGroupAgents, true, DeploymentModeActiveFailover, EnvironmentProduction))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(1)}.Validate(ServerGroupDBServers, true, DeploymentModeCluster, EnvironmentProduction))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(1)}.Validate(ServerGroupCoordinators, true, DeploymentModeCluster, EnvironmentProduction))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(1)}.Validate(ServerGroupSyncMasters, true, DeploymentModeCluster, EnvironmentProduction))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(1)}.Validate(ServerGroupSyncWorkers, true, DeploymentModeCluster, EnvironmentProduction))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(2), MinCount: util.NewInt(5), MaxCount: util.NewInt(1)}.Validate(ServerGroupCoordinators, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(6), MaxCount: util.NewInt(5)}.Validate(ServerGroupCoordinators, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(1), MinCount: util.NewInt(2)}.Validate(ServerGroupCoordinators, true, DeploymentModeCluster, EnvironmentDevelopment))
}
func TestServerGroupSpecDefault(t *testing.T) {
def := func(spec ServerGroupSpec, group ServerGroup, used bool, mode DeploymentMode) ServerGroupSpec {
spec.SetDefaults(group, used, mode)
return spec
}
assert.Equal(t, 1, def(ServerGroupSpec{}, ServerGroupSingle, true, DeploymentModeSingle).GetCount())
assert.Equal(t, 2, def(ServerGroupSpec{}, ServerGroupSingle, true, DeploymentModeActiveFailover).GetCount())
assert.Equal(t, 0, def(ServerGroupSpec{}, ServerGroupSingle, false, DeploymentModeCluster).GetCount())
assert.Equal(t, 0, def(ServerGroupSpec{}, ServerGroupAgents, false, DeploymentModeSingle).GetCount())
assert.Equal(t, 3, def(ServerGroupSpec{}, ServerGroupAgents, true, DeploymentModeActiveFailover).GetCount())
assert.Equal(t, 3, def(ServerGroupSpec{}, ServerGroupAgents, true, DeploymentModeCluster).GetCount())
assert.Equal(t, 0, def(ServerGroupSpec{}, ServerGroupDBServers, false, DeploymentModeSingle).GetCount())
assert.Equal(t, 0, def(ServerGroupSpec{}, ServerGroupDBServers, false, DeploymentModeActiveFailover).GetCount())
assert.Equal(t, 3, def(ServerGroupSpec{}, ServerGroupDBServers, true, DeploymentModeCluster).GetCount())
assert.Equal(t, 0, def(ServerGroupSpec{}, ServerGroupCoordinators, false, DeploymentModeSingle).GetCount())
assert.Equal(t, 0, def(ServerGroupSpec{}, ServerGroupCoordinators, false, DeploymentModeActiveFailover).GetCount())
assert.Equal(t, 3, def(ServerGroupSpec{}, ServerGroupCoordinators, true, DeploymentModeCluster).GetCount())
assert.Equal(t, 0, def(ServerGroupSpec{}, ServerGroupSyncMasters, false, DeploymentModeSingle).GetCount())
assert.Equal(t, 0, def(ServerGroupSpec{}, ServerGroupSyncMasters, false, DeploymentModeActiveFailover).GetCount())
assert.Equal(t, 3, def(ServerGroupSpec{}, ServerGroupSyncMasters, true, DeploymentModeCluster).GetCount())
assert.Equal(t, 0, def(ServerGroupSpec{}, ServerGroupSyncWorkers, false, DeploymentModeSingle).GetCount())
assert.Equal(t, 0, def(ServerGroupSpec{}, ServerGroupSyncWorkers, false, DeploymentModeActiveFailover).GetCount())
assert.Equal(t, 3, def(ServerGroupSpec{}, ServerGroupSyncWorkers, true, DeploymentModeCluster).GetCount())
for _, g := range AllServerGroups {
assert.Equal(t, 0, len(def(ServerGroupSpec{}, g, true, DeploymentModeSingle).Args))
assert.Equal(t, "", def(ServerGroupSpec{}, g, true, DeploymentModeSingle).GetStorageClassName())
}
}
func TestServerGroupSpecValidateArgs(t *testing.T) {
// Valid
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(1), Args: []string{}}.Validate(ServerGroupSingle, true, DeploymentModeSingle, EnvironmentDevelopment))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(1), Args: []string{"--master.endpoint"}}.Validate(ServerGroupSingle, true, DeploymentModeSingle, EnvironmentDevelopment))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(1), Args: []string{}}.Validate(ServerGroupSyncMasters, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Nil(t, ServerGroupSpec{Count: util.NewInt(1), Args: []string{"--server.authentication=true"}}.Validate(ServerGroupSyncMasters, true, DeploymentModeCluster, EnvironmentDevelopment))
// Invalid
assert.Error(t, ServerGroupSpec{Count: util.NewInt(1), Args: []string{"--server.authentication=true"}}.Validate(ServerGroupSingle, true, DeploymentModeSingle, EnvironmentDevelopment))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(1), Args: []string{"--server.authentication", "true"}}.Validate(ServerGroupSingle, true, DeploymentModeSingle, EnvironmentDevelopment))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(1), Args: []string{"--master.endpoint=http://something"}}.Validate(ServerGroupSyncMasters, true, DeploymentModeCluster, EnvironmentDevelopment))
assert.Error(t, ServerGroupSpec{Count: util.NewInt(1), Args: []string{"--mq.type=strange"}}.Validate(ServerGroupSyncMasters, true, DeploymentModeCluster, EnvironmentDevelopment))
}

View file

@ -1,65 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestServerGroupAsRole(t *testing.T) {
assert.Equal(t, "single", ServerGroupSingle.AsRole())
assert.Equal(t, "agent", ServerGroupAgents.AsRole())
assert.Equal(t, "dbserver", ServerGroupDBServers.AsRole())
assert.Equal(t, "coordinator", ServerGroupCoordinators.AsRole())
assert.Equal(t, "syncmaster", ServerGroupSyncMasters.AsRole())
assert.Equal(t, "syncworker", ServerGroupSyncWorkers.AsRole())
}
func TestServerGroupAsRoleAbbreviated(t *testing.T) {
assert.Equal(t, "sngl", ServerGroupSingle.AsRoleAbbreviated())
assert.Equal(t, "agnt", ServerGroupAgents.AsRoleAbbreviated())
assert.Equal(t, "prmr", ServerGroupDBServers.AsRoleAbbreviated())
assert.Equal(t, "crdn", ServerGroupCoordinators.AsRoleAbbreviated())
assert.Equal(t, "syma", ServerGroupSyncMasters.AsRoleAbbreviated())
assert.Equal(t, "sywo", ServerGroupSyncWorkers.AsRoleAbbreviated())
}
func TestServerGroupIsArangod(t *testing.T) {
assert.True(t, ServerGroupSingle.IsArangod())
assert.True(t, ServerGroupAgents.IsArangod())
assert.True(t, ServerGroupDBServers.IsArangod())
assert.True(t, ServerGroupCoordinators.IsArangod())
assert.False(t, ServerGroupSyncMasters.IsArangod())
assert.False(t, ServerGroupSyncWorkers.IsArangod())
}
func TestServerGroupIsArangosync(t *testing.T) {
assert.False(t, ServerGroupSingle.IsArangosync())
assert.False(t, ServerGroupAgents.IsArangosync())
assert.False(t, ServerGroupDBServers.IsArangosync())
assert.False(t, ServerGroupCoordinators.IsArangosync())
assert.True(t, ServerGroupSyncMasters.IsArangosync())
assert.True(t, ServerGroupSyncWorkers.IsArangosync())
}

View file

@ -1,80 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"strings"
"github.com/pkg/errors"
)
// StorageEngine specifies the type of storage engine used by the cluster
type StorageEngine string
const (
// StorageEngineMMFiles yields a cluster using the mmfiles storage engine
StorageEngineMMFiles StorageEngine = "MMFiles"
// StorageEngineRocksDB yields a cluster using the rocksdb storage engine
StorageEngineRocksDB StorageEngine = "RocksDB"
)
// Validate the storage engine.
// Return errors when validation fails, nil on success.
func (se StorageEngine) Validate() error {
switch se {
case StorageEngineMMFiles, StorageEngineRocksDB:
return nil
default:
return maskAny(errors.Wrapf(ValidationError, "Unknown storage engine: '%s'", string(se)))
}
}
// AsArangoArgument returns the value for the given storage engine as it is to be used
// for arangod's --server.storage-engine option.
func (se StorageEngine) AsArangoArgument() string {
return strings.ToLower(string(se))
}
// NewStorageEngine returns a reference to a string with given value.
func NewStorageEngine(input StorageEngine) *StorageEngine {
return &input
}
// NewStorageEngineOrNil returns nil if input is nil, otherwise returns a clone of the given value.
func NewStorageEngineOrNil(input *StorageEngine) *StorageEngine {
if input == nil {
return nil
}
return NewStorageEngine(*input)
}
// StorageEngineOrDefault returns the default value (or empty string) if input is nil, otherwise returns the referenced value.
func StorageEngineOrDefault(input *StorageEngine, defaultValue ...StorageEngine) StorageEngine {
if input == nil {
if len(defaultValue) > 0 {
return defaultValue[0]
}
return ""
}
return *input
}

View file

@ -1,41 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestStorageEngineValidate(t *testing.T) {
// Valid
assert.Nil(t, StorageEngine("MMFiles").Validate())
assert.Nil(t, StorageEngine("RocksDB").Validate())
// Not valid
assert.Error(t, StorageEngine("").Validate())
assert.Error(t, StorageEngine(" mmfiles").Validate())
assert.Error(t, StorageEngine("mmfiles").Validate())
assert.Error(t, StorageEngine("rocksdb").Validate())
}

View file

@ -1,87 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
)
// SyncAuthenticationSpec holds dc2dc sync authentication specific configuration settings
type SyncAuthenticationSpec struct {
JWTSecretName *string `json:"jwtSecretName,omitempty"` // JWT secret for sync masters
ClientCASecretName *string `json:"clientCASecretName,omitempty"` // Secret containing client authentication CA
}
// GetJWTSecretName returns the value of jwtSecretName.
func (s SyncAuthenticationSpec) GetJWTSecretName() string {
return util.StringOrDefault(s.JWTSecretName)
}
// GetClientCASecretName returns the value of clientCASecretName.
func (s SyncAuthenticationSpec) GetClientCASecretName() string {
return util.StringOrDefault(s.ClientCASecretName)
}
// Validate the given spec
func (s SyncAuthenticationSpec) Validate() error {
if err := k8sutil.ValidateResourceName(s.GetJWTSecretName()); err != nil {
return maskAny(err)
}
if err := k8sutil.ValidateResourceName(s.GetClientCASecretName()); err != nil {
return maskAny(err)
}
return nil
}
// SetDefaults fills in missing defaults
func (s *SyncAuthenticationSpec) SetDefaults(defaultJWTSecretName, defaultClientCASecretName string) {
if s.GetJWTSecretName() == "" {
// Note that we don't check for nil here, since even a specified, but empty
// string should result in the default value.
s.JWTSecretName = util.NewString(defaultJWTSecretName)
}
if s.GetClientCASecretName() == "" {
// Note that we don't check for nil here, since even a specified, but empty
// string should result in the default value.
s.ClientCASecretName = util.NewString(defaultClientCASecretName)
}
}
// SetDefaultsFrom fills unspecified fields with a value from given source spec.
func (s *SyncAuthenticationSpec) SetDefaultsFrom(source SyncAuthenticationSpec) {
if s.JWTSecretName == nil {
s.JWTSecretName = util.NewStringOrNil(source.JWTSecretName)
}
if s.ClientCASecretName == nil {
s.ClientCASecretName = util.NewStringOrNil(source.ClientCASecretName)
}
}
// ResetImmutableFields replaces all immutable fields in the given target with values from the source spec.
// It returns a list of fields that have been reset.
// Field names are relative to given field prefix.
func (s SyncAuthenticationSpec) ResetImmutableFields(fieldPrefix string, target *SyncAuthenticationSpec) []string {
var resetFields []string
return resetFields
}

View file

@ -1,102 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"fmt"
"net"
"net/url"
"strconv"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
)
// SyncExternalAccessSpec holds configuration for the external access provided for the sync deployment.
type SyncExternalAccessSpec struct {
ExternalAccessSpec
MasterEndpoint []string `json:"masterEndpoint,omitempty"`
AccessPackageSecretNames []string `json:"accessPackageSecretNames,omitempty"`
}
// GetMasterEndpoint returns the value of masterEndpoint.
func (s SyncExternalAccessSpec) GetMasterEndpoint() []string {
return s.MasterEndpoint
}
// GetAccessPackageSecretNames returns the value of accessPackageSecretNames.
func (s SyncExternalAccessSpec) GetAccessPackageSecretNames() []string {
return s.AccessPackageSecretNames
}
// ResolveMasterEndpoint returns the value of `--master.endpoint` option passed to arangosync.
func (s SyncExternalAccessSpec) ResolveMasterEndpoint(syncServiceHostName string, syncServicePort int) []string {
if len(s.MasterEndpoint) > 0 {
return s.MasterEndpoint
}
if ip := s.GetLoadBalancerIP(); ip != "" {
syncServiceHostName = ip
}
return []string{"https://" + net.JoinHostPort(syncServiceHostName, strconv.Itoa(syncServicePort))}
}
// Validate the given spec
func (s SyncExternalAccessSpec) Validate() error {
if err := s.ExternalAccessSpec.Validate(); err != nil {
return maskAny(err)
}
for _, ep := range s.MasterEndpoint {
if _, err := url.Parse(ep); err != nil {
return maskAny(fmt.Errorf("Failed to parse master endpoint '%s': %s", ep, err))
}
}
for _, name := range s.AccessPackageSecretNames {
if err := k8sutil.ValidateResourceName(name); err != nil {
return maskAny(fmt.Errorf("Invalid name '%s' in accessPackageSecretNames: %s", name, err))
}
}
return nil
}
// SetDefaults fills in missing defaults
func (s *SyncExternalAccessSpec) SetDefaults() {
s.ExternalAccessSpec.SetDefaults()
}
// SetDefaultsFrom fills unspecified fields with a value from given source spec.
func (s *SyncExternalAccessSpec) SetDefaultsFrom(source SyncExternalAccessSpec) {
s.ExternalAccessSpec.SetDefaultsFrom(source.ExternalAccessSpec)
if s.MasterEndpoint == nil && source.MasterEndpoint != nil {
s.MasterEndpoint = append([]string{}, source.MasterEndpoint...)
}
if s.AccessPackageSecretNames == nil && source.AccessPackageSecretNames != nil {
s.AccessPackageSecretNames = append([]string{}, source.AccessPackageSecretNames...)
}
}
// ResetImmutableFields replaces all immutable fields in the given target with values from the source spec.
// It returns a list of fields that have been reset.
// Field names are relative to given field prefix.
func (s SyncExternalAccessSpec) ResetImmutableFields(fieldPrefix string, target *SyncExternalAccessSpec) []string {
result := s.ExternalAccessSpec.ResetImmutableFields(fieldPrefix, &s.ExternalAccessSpec)
return result
}

View file

@ -1,116 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"github.com/pkg/errors"
"github.com/arangodb/kube-arangodb/pkg/util"
)
// SyncSpec holds dc2dc replication specific configuration settings
type SyncSpec struct {
Enabled *bool `json:"enabled,omitempty"`
ExternalAccess SyncExternalAccessSpec `json:"externalAccess"`
Authentication SyncAuthenticationSpec `json:"auth"`
TLS TLSSpec `json:"tls"`
Monitoring MonitoringSpec `json:"monitoring"`
Image *string `json:"image"`
}
// IsEnabled returns the value of enabled.
func (s SyncSpec) IsEnabled() bool {
return util.BoolOrDefault(s.Enabled)
}
// GetSyncImage returns the syncer image or empty string
func (s SyncSpec) GetSyncImage() string {
return util.StringOrDefault(s.Image)
}
// HasSyncImage returns whether a special sync image is set
func (s SyncSpec) HasSyncImage() bool {
return s.GetSyncImage() != ""
}
// Validate the given spec
func (s SyncSpec) Validate(mode DeploymentMode) error {
if s.IsEnabled() && !mode.SupportsSync() {
return maskAny(errors.Wrapf(ValidationError, "Cannot enable sync with mode: '%s'", mode))
}
if s.IsEnabled() {
if err := s.ExternalAccess.Validate(); err != nil {
return maskAny(err)
}
if err := s.Authentication.Validate(); err != nil {
return maskAny(err)
}
if err := s.TLS.Validate(); err != nil {
return maskAny(err)
}
}
if err := s.Monitoring.Validate(); err != nil {
return maskAny(err)
}
return nil
}
// SetDefaults fills in missing defaults
func (s *SyncSpec) SetDefaults(defaultJWTSecretName, defaultClientAuthCASecretName, defaultTLSCASecretName, defaultMonitoringSecretName string) {
s.ExternalAccess.SetDefaults()
s.Authentication.SetDefaults(defaultJWTSecretName, defaultClientAuthCASecretName)
s.TLS.SetDefaults(defaultTLSCASecretName)
s.Monitoring.SetDefaults(defaultMonitoringSecretName)
}
// SetDefaultsFrom fills unspecified fields with a value from given source spec.
func (s *SyncSpec) SetDefaultsFrom(source SyncSpec) {
if s.Enabled == nil {
s.Enabled = util.NewBoolOrNil(source.Enabled)
}
if s.Image == nil {
s.Image = util.NewStringOrNil(source.Image)
}
s.ExternalAccess.SetDefaultsFrom(source.ExternalAccess)
s.Authentication.SetDefaultsFrom(source.Authentication)
s.TLS.SetDefaultsFrom(source.TLS)
s.Monitoring.SetDefaultsFrom(source.Monitoring)
}
// ResetImmutableFields replaces all immutable fields in the given target with values from the source spec.
// It returns a list of fields that have been reset.
// Field names are relative to given field prefix.
func (s SyncSpec) ResetImmutableFields(fieldPrefix string, target *SyncSpec) []string {
var resetFields []string
if list := s.ExternalAccess.ResetImmutableFields(fieldPrefix+".externalAccess", &target.ExternalAccess); len(list) > 0 {
resetFields = append(resetFields, list...)
}
if list := s.Authentication.ResetImmutableFields(fieldPrefix+".auth", &target.Authentication); len(list) > 0 {
resetFields = append(resetFields, list...)
}
if s.GetSyncImage() != target.GetSyncImage() {
resetFields = append(resetFields, fieldPrefix+".image")
}
return resetFields
}

View file

@ -1,105 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"testing"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/stretchr/testify/assert"
)
func TestSyncSpecValidate(t *testing.T) {
// Valid
auth := SyncAuthenticationSpec{JWTSecretName: util.NewString("foo"), ClientCASecretName: util.NewString("foo-client")}
tls := TLSSpec{CASecretName: util.NewString("None")}
assert.Nil(t, SyncSpec{Authentication: auth}.Validate(DeploymentModeSingle))
assert.Nil(t, SyncSpec{Authentication: auth}.Validate(DeploymentModeActiveFailover))
assert.Nil(t, SyncSpec{Authentication: auth}.Validate(DeploymentModeCluster))
assert.Nil(t, SyncSpec{Authentication: auth, TLS: tls, Enabled: util.NewBool(true)}.Validate(DeploymentModeCluster))
// Not valid
assert.Error(t, SyncSpec{Authentication: auth, TLS: tls, Enabled: util.NewBool(true)}.Validate(DeploymentModeSingle))
assert.Error(t, SyncSpec{Authentication: auth, TLS: tls, Enabled: util.NewBool(true)}.Validate(DeploymentModeActiveFailover))
}
func TestSyncSpecSetDefaults(t *testing.T) {
def := func(spec SyncSpec) SyncSpec {
spec.SetDefaults("test-jwt", "test-client-auth-ca", "test-tls-ca", "test-mon")
return spec
}
assert.False(t, def(SyncSpec{}).IsEnabled())
assert.False(t, def(SyncSpec{Enabled: util.NewBool(false)}).IsEnabled())
assert.True(t, def(SyncSpec{Enabled: util.NewBool(true)}).IsEnabled())
assert.Equal(t, "test-jwt", def(SyncSpec{}).Authentication.GetJWTSecretName())
assert.Equal(t, "test-mon", def(SyncSpec{}).Monitoring.GetTokenSecretName())
assert.Equal(t, "foo", def(SyncSpec{Authentication: SyncAuthenticationSpec{JWTSecretName: util.NewString("foo")}}).Authentication.GetJWTSecretName())
}
func TestSyncSpecResetImmutableFields(t *testing.T) {
tests := []struct {
Original SyncSpec
Target SyncSpec
Expected SyncSpec
Result []string
}{
// Valid "changes"
{
SyncSpec{Enabled: util.NewBool(false)},
SyncSpec{Enabled: util.NewBool(true)},
SyncSpec{Enabled: util.NewBool(true)},
nil,
},
{
SyncSpec{Enabled: util.NewBool(true)},
SyncSpec{Enabled: util.NewBool(false)},
SyncSpec{Enabled: util.NewBool(false)},
nil,
},
{
SyncSpec{Authentication: SyncAuthenticationSpec{JWTSecretName: util.NewString("None"), ClientCASecretName: util.NewString("some")}},
SyncSpec{Authentication: SyncAuthenticationSpec{JWTSecretName: util.NewString("None"), ClientCASecretName: util.NewString("some")}},
SyncSpec{Authentication: SyncAuthenticationSpec{JWTSecretName: util.NewString("None"), ClientCASecretName: util.NewString("some")}},
nil,
},
{
SyncSpec{Authentication: SyncAuthenticationSpec{JWTSecretName: util.NewString("foo"), ClientCASecretName: util.NewString("some")}},
SyncSpec{Authentication: SyncAuthenticationSpec{JWTSecretName: util.NewString("foo"), ClientCASecretName: util.NewString("some")}},
SyncSpec{Authentication: SyncAuthenticationSpec{JWTSecretName: util.NewString("foo"), ClientCASecretName: util.NewString("some")}},
nil,
},
{
SyncSpec{Authentication: SyncAuthenticationSpec{JWTSecretName: util.NewString("foo"), ClientCASecretName: util.NewString("some")}},
SyncSpec{Authentication: SyncAuthenticationSpec{JWTSecretName: util.NewString("foo2"), ClientCASecretName: util.NewString("some")}},
SyncSpec{Authentication: SyncAuthenticationSpec{JWTSecretName: util.NewString("foo2"), ClientCASecretName: util.NewString("some")}},
nil,
},
}
for _, test := range tests {
result := test.Original.ResetImmutableFields("test", &test.Target)
assert.Equal(t, test.Result, result)
assert.Equal(t, test.Expected, test.Target)
}
}

View file

@ -1,128 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"fmt"
"net"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
"github.com/arangodb/kube-arangodb/pkg/util/validation"
)
const (
defaultTLSTTL = Duration("2610h") // About 3 month
)
// TLSSpec holds TLS specific configuration settings
type TLSSpec struct {
CASecretName *string `json:"caSecretName,omitempty"`
AltNames []string `json:"altNames,omitempty"`
TTL *Duration `json:"ttl,omitempty"`
}
const (
// CASecretNameDisabled is the value of CASecretName to use for disabling authentication.
CASecretNameDisabled = "None"
)
// GetCASecretName returns the value of caSecretName.
func (s TLSSpec) GetCASecretName() string {
return util.StringOrDefault(s.CASecretName)
}
// GetAltNames returns the value of altNames.
func (s TLSSpec) GetAltNames() []string {
return s.AltNames
}
// GetTTL returns the value of ttl.
func (s TLSSpec) GetTTL() Duration {
return DurationOrDefault(s.TTL)
}
// IsSecure returns true when a CA secret has been set, false otherwise.
func (s TLSSpec) IsSecure() bool {
return s.GetCASecretName() != CASecretNameDisabled
}
// GetParsedAltNames splits the list of AltNames into DNS names, IP addresses & email addresses.
// When an entry is not valid for any of those categories, an error is returned.
func (s TLSSpec) GetParsedAltNames() (dnsNames, ipAddresses, emailAddresses []string, err error) {
for _, name := range s.GetAltNames() {
if net.ParseIP(name) != nil {
ipAddresses = append(ipAddresses, name)
} else if validation.IsValidDNSName(name) {
dnsNames = append(dnsNames, name)
} else if validation.IsValidEmailAddress(name) {
emailAddresses = append(emailAddresses, name)
} else {
return nil, nil, nil, maskAny(fmt.Errorf("'%s' is not a valid alternate name", name))
}
}
return dnsNames, ipAddresses, emailAddresses, nil
}
// Validate the given spec
func (s TLSSpec) Validate() error {
if s.IsSecure() {
if err := k8sutil.ValidateResourceName(s.GetCASecretName()); err != nil {
return maskAny(err)
}
if _, _, _, err := s.GetParsedAltNames(); err != nil {
return maskAny(err)
}
if err := s.GetTTL().Validate(); err != nil {
return maskAny(err)
}
}
return nil
}
// SetDefaults fills in missing defaults
func (s *TLSSpec) SetDefaults(defaultCASecretName string) {
if s.GetCASecretName() == "" {
// Note that we don't check for nil here, since even a specified, but empty
// string should result in the default value.
s.CASecretName = util.NewString(defaultCASecretName)
}
if s.GetTTL() == "" {
// Note that we don't check for nil here, since even a specified, but zero
// should result in the default value.
s.TTL = NewDuration(defaultTLSTTL)
}
}
// SetDefaultsFrom fills unspecified fields with a value from given source spec.
func (s *TLSSpec) SetDefaultsFrom(source TLSSpec) {
if s.CASecretName == nil {
s.CASecretName = util.NewStringOrNil(source.CASecretName)
}
if s.AltNames == nil {
s.AltNames = source.AltNames
}
if s.TTL == nil {
s.TTL = NewDurationOrNil(source.TTL)
}
}

View file

@ -1,66 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"testing"
"time"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/stretchr/testify/assert"
)
func TestTLSSpecValidate(t *testing.T) {
// Valid
assert.Nil(t, TLSSpec{CASecretName: util.NewString("foo")}.Validate())
assert.Nil(t, TLSSpec{CASecretName: util.NewString("None")}.Validate())
assert.Nil(t, TLSSpec{CASecretName: util.NewString("None"), AltNames: []string{}}.Validate())
assert.Nil(t, TLSSpec{CASecretName: util.NewString("None"), AltNames: []string{"foo"}}.Validate())
assert.Nil(t, TLSSpec{CASecretName: util.NewString("None"), AltNames: []string{"email@example.com", "127.0.0.1"}}.Validate())
// Not valid
assert.Error(t, TLSSpec{CASecretName: nil}.Validate())
assert.Error(t, TLSSpec{CASecretName: util.NewString("")}.Validate())
assert.Error(t, TLSSpec{CASecretName: util.NewString("Foo")}.Validate())
assert.Error(t, TLSSpec{CASecretName: util.NewString("foo"), AltNames: []string{"@@"}}.Validate())
}
func TestTLSSpecIsSecure(t *testing.T) {
assert.True(t, TLSSpec{CASecretName: util.NewString("")}.IsSecure())
assert.True(t, TLSSpec{CASecretName: util.NewString("foo")}.IsSecure())
assert.False(t, TLSSpec{CASecretName: util.NewString("None")}.IsSecure())
}
func TestTLSSpecSetDefaults(t *testing.T) {
def := func(spec TLSSpec) TLSSpec {
spec.SetDefaults("")
return spec
}
assert.Equal(t, "", def(TLSSpec{}).GetCASecretName())
assert.Equal(t, "foo", def(TLSSpec{CASecretName: util.NewString("foo")}).GetCASecretName())
assert.Len(t, def(TLSSpec{}).GetAltNames(), 0)
assert.Len(t, def(TLSSpec{AltNames: []string{"foo.local"}}).GetAltNames(), 1)
assert.Equal(t, defaultTLSTTL, def(TLSSpec{}).GetTTL())
assert.Equal(t, time.Hour, def(TLSSpec{TTL: NewDuration("1h")}).GetTTL().AsDuration())
}

File diff suppressed because it is too large Load diff

View file

@ -1,32 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
// CollectionStatus contains the status of a single collection.
type CollectionStatus struct {
// Name of the collection
Name string `json:"name"`
// Replication status per shard.
// The list is ordered by shard index (0..noShards-1)
Shards []ShardStatus `json:"shards,omitempty"`
}

View file

@ -1,131 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// ConditionType is a strongly typed condition name
type ConditionType string
const (
// ConditionTypeConfigured indicates that the replication has been configured.
ConditionTypeConfigured ConditionType = "Configured"
)
// Condition represents one current condition of a deployment or deployment member.
// A condition might not show up if it is not happening.
// For example, if a cluster is not upgrading, the Upgrading condition would not show up.
type Condition struct {
// Type of condition.
Type ConditionType `json:"type"`
// Status of the condition, one of True, False, Unknown.
Status v1.ConditionStatus `json:"status"`
// The last time this condition was updated.
LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"`
// Last time the condition transitioned from one status to another.
LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
// The reason for the condition's last transition.
Reason string `json:"reason,omitempty"`
// A human readable message indicating details about the transition.
Message string `json:"message,omitempty"`
}
// ConditionList is a list of conditions.
// Each type is allowed only once.
type ConditionList []Condition
// IsTrue return true when a condition with given type exists and its status is `True`.
func (list ConditionList) IsTrue(conditionType ConditionType) bool {
c, found := list.Get(conditionType)
return found && c.Status == v1.ConditionTrue
}
// Get a condition by type.
// Returns true if found, false if not found.
func (list ConditionList) Get(conditionType ConditionType) (Condition, bool) {
for _, x := range list {
if x.Type == conditionType {
return x, true
}
}
// Not found
return Condition{}, false
}
// Update the condition, replacing an old condition with same type (if any)
// Returns true when changes were made, false otherwise.
func (list *ConditionList) Update(conditionType ConditionType, status bool, reason, message string) bool {
src := *list
statusX := v1.ConditionFalse
if status {
statusX = v1.ConditionTrue
}
for i, x := range src {
if x.Type == conditionType {
if x.Status != statusX {
// Transition to another status
src[i].Status = statusX
now := metav1.Now()
src[i].LastTransitionTime = now
src[i].LastUpdateTime = now
src[i].Reason = reason
src[i].Message = message
} else if x.Reason != reason || x.Message != message {
src[i].LastUpdateTime = metav1.Now()
src[i].Reason = reason
src[i].Message = message
} else {
return false
}
return true
}
}
// Not found
now := metav1.Now()
*list = append(src, Condition{
Type: conditionType,
LastUpdateTime: now,
LastTransitionTime: now,
Status: statusX,
Reason: reason,
Message: message,
})
return true
}
// Remove the condition with given type.
// Returns true if removed, or false if not found.
func (list *ConditionList) Remove(conditionType ConditionType) bool {
src := *list
for i, x := range src {
if x.Type == conditionType {
*list = append(src[:i], src[i+1:]...)
return true
}
}
// Not found
return false
}

View file

@ -1,95 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestConditionListIsTrue(t *testing.T) {
assert.False(t, ConditionList{}.IsTrue(ConditionTypeConfigured))
cl := ConditionList{}
cl.Update(ConditionTypeConfigured, true, "test", "msg")
assert.True(t, cl.IsTrue(ConditionTypeConfigured))
//assert.False(t, cl.IsTrue(ConditionTypeTerminated))
cl.Update(ConditionTypeConfigured, false, "test", "msg")
assert.False(t, cl.IsTrue(ConditionTypeConfigured))
cl.Remove(ConditionTypeConfigured)
assert.False(t, cl.IsTrue(ConditionTypeConfigured))
assert.Equal(t, 0, len(cl))
}
func TestConditionListGet(t *testing.T) {
conv := func(c Condition, b bool) []interface{} {
return []interface{}{c, b}
}
cl := ConditionList{}
assert.EqualValues(t, conv(Condition{}, false), conv(cl.Get(ConditionTypeConfigured)))
cl.Update(ConditionTypeConfigured, false, "test", "msg")
assert.EqualValues(t, conv(cl[0], true), conv(cl.Get(ConditionTypeConfigured)))
}
func TestConditionListUpdate(t *testing.T) {
cl := ConditionList{}
assert.Equal(t, 0, len(cl))
assert.True(t, cl.Update(ConditionTypeConfigured, true, "test", "msg"))
assert.True(t, cl.IsTrue(ConditionTypeConfigured))
assert.Equal(t, 1, len(cl))
assert.False(t, cl.Update(ConditionTypeConfigured, true, "test", "msg"))
assert.True(t, cl.IsTrue(ConditionTypeConfigured))
assert.Equal(t, 1, len(cl))
assert.True(t, cl.Update(ConditionTypeConfigured, false, "test", "msg"))
assert.False(t, cl.IsTrue(ConditionTypeConfigured))
assert.Equal(t, 1, len(cl))
assert.True(t, cl.Update(ConditionTypeConfigured, false, "test2", "msg"))
assert.False(t, cl.IsTrue(ConditionTypeConfigured))
assert.Equal(t, 1, len(cl))
assert.True(t, cl.Update(ConditionTypeConfigured, false, "test2", "msg2"))
assert.False(t, cl.IsTrue(ConditionTypeConfigured))
assert.Equal(t, 1, len(cl))
}
func TestConditionListRemove(t *testing.T) {
cl := ConditionList{}
assert.Equal(t, 0, len(cl))
cl.Update(ConditionTypeConfigured, true, "test", "msg")
assert.Equal(t, 1, len(cl))
assert.True(t, cl.Remove(ConditionTypeConfigured))
assert.Equal(t, 0, len(cl))
assert.False(t, cl.Remove(ConditionTypeConfigured))
assert.Equal(t, 0, len(cl))
}

View file

@ -1,32 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
// DatabaseStatus contains the status of a single database.
type DatabaseStatus struct {
// Name of the database
Name string `json:"name"`
// Collections holds the replication status of each collection in the database.
// List is ordered by name of the collection.
Collections []CollectionStatus `json:"collections,omitempty"`
}

View file

@ -1,25 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
// +k8s:deepcopy-gen=package
// +groupName=replication.database.arangodb.com
package v1alpha

View file

@ -1,89 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
"github.com/pkg/errors"
)
// EndpointAuthenticationSpec contains the specification to authentication with the syncmasters
// in either source or destination endpoint.
type EndpointAuthenticationSpec struct {
// KeyfileSecretName holds the name of a Secret containing a client authentication
// certificate formatted at keyfile in a `tls.keyfile` field.
KeyfileSecretName *string `json:"keyfileSecretName,omitempty"`
// UserSecretName holds the name of a Secret containing a `username` & `password`
// field used for basic authentication.
// The user identified by the username must have write access in the `_system` database
// of the ArangoDB cluster at the endpoint.
UserSecretName *string `json:"userSecretName,omitempty"`
}
// GetKeyfileSecretName returns the value of keyfileSecretName.
func (s EndpointAuthenticationSpec) GetKeyfileSecretName() string {
return util.StringOrDefault(s.KeyfileSecretName)
}
// GetUserSecretName returns the value of userSecretName.
func (s EndpointAuthenticationSpec) GetUserSecretName() string {
return util.StringOrDefault(s.UserSecretName)
}
// Validate the given spec, returning an error on validation
// problems or nil if all ok.
func (s EndpointAuthenticationSpec) Validate(keyfileSecretNameRequired bool) error {
if err := k8sutil.ValidateOptionalResourceName(s.GetKeyfileSecretName()); err != nil {
return maskAny(err)
}
if err := k8sutil.ValidateOptionalResourceName(s.GetUserSecretName()); err != nil {
return maskAny(err)
}
if keyfileSecretNameRequired && s.GetKeyfileSecretName() == "" {
return maskAny(errors.Wrapf(ValidationError, "Provide a keyfileSecretName"))
}
return nil
}
// SetDefaults fills empty field with default values.
func (s *EndpointAuthenticationSpec) SetDefaults() {
}
// SetDefaultsFrom fills empty field with default values from the given source.
func (s *EndpointAuthenticationSpec) SetDefaultsFrom(source EndpointAuthenticationSpec) {
if s.KeyfileSecretName == nil {
s.KeyfileSecretName = util.NewStringOrNil(source.KeyfileSecretName)
}
if s.UserSecretName == nil {
s.UserSecretName = util.NewStringOrNil(source.UserSecretName)
}
}
// ResetImmutableFields replaces all immutable fields in the given target with values from the source spec.
// It returns a list of fields that have been reset.
// Field names are relative to `spec.`.
func (s EndpointAuthenticationSpec) ResetImmutableFields(target *EndpointAuthenticationSpec, fieldPrefix string) []string {
var result []string
return result
}

View file

@ -1,111 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"net/url"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
"github.com/pkg/errors"
)
// EndpointSpec contains the specification used to reach the syncmasters
// in either source or destination mode.
type EndpointSpec struct {
// DeploymentName holds the name of an ArangoDeployment resource.
// If set this provides default values for masterEndpoint, auth & tls.
DeploymentName *string `json:"deploymentName,omitempty"`
// MasterEndpoint holds a list of URLs used to reach the syncmaster(s).
MasterEndpoint []string `json:"masterEndpoint,omitempty"`
// Authentication holds settings needed to authentication at the syncmaster.
Authentication EndpointAuthenticationSpec `json:"auth"`
// TLS holds settings needed to verify the TLS connection to the syncmaster.
TLS EndpointTLSSpec `json:"tls"`
}
// GetDeploymentName returns the value of deploymentName.
func (s EndpointSpec) GetDeploymentName() string {
return util.StringOrDefault(s.DeploymentName)
}
// HasDeploymentName returns the true when a non-empty deployment name it set.
func (s EndpointSpec) HasDeploymentName() bool {
return s.GetDeploymentName() != ""
}
// Validate the given spec, returning an error on validation
// problems or nil if all ok.
func (s EndpointSpec) Validate(isSourceEndpoint bool) error {
if err := k8sutil.ValidateOptionalResourceName(s.GetDeploymentName()); err != nil {
return maskAny(err)
}
for _, ep := range s.MasterEndpoint {
if _, err := url.Parse(ep); err != nil {
return maskAny(errors.Wrapf(ValidationError, "Invalid master endpoint '%s': %s", ep, err))
}
}
hasDeploymentName := s.HasDeploymentName()
if !hasDeploymentName && len(s.MasterEndpoint) == 0 {
return maskAny(errors.Wrapf(ValidationError, "Provide a deploy name or at least one master endpoint"))
}
if err := s.Authentication.Validate(isSourceEndpoint || !hasDeploymentName); err != nil {
return maskAny(err)
}
if err := s.TLS.Validate(!hasDeploymentName); err != nil {
return maskAny(err)
}
return nil
}
// SetDefaults fills empty field with default values.
func (s *EndpointSpec) SetDefaults() {
s.Authentication.SetDefaults()
s.TLS.SetDefaults()
}
// SetDefaultsFrom fills empty field with default values from the given source.
func (s *EndpointSpec) SetDefaultsFrom(source EndpointSpec) {
if s.DeploymentName == nil {
s.DeploymentName = util.NewStringOrNil(source.DeploymentName)
}
s.Authentication.SetDefaultsFrom(source.Authentication)
s.TLS.SetDefaultsFrom(source.TLS)
}
// ResetImmutableFields replaces all immutable fields in the given target with values from the source spec.
// It returns a list of fields that have been reset.
// Field names are relative to `spec.`.
func (s EndpointSpec) ResetImmutableFields(target *EndpointSpec, fieldPrefix string) []string {
var result []string
if s.GetDeploymentName() != target.GetDeploymentName() {
result = append(result, fieldPrefix+"deploymentName")
}
if list := s.Authentication.ResetImmutableFields(&target.Authentication, fieldPrefix+"auth."); len(list) > 0 {
result = append(result, list...)
}
if list := s.TLS.ResetImmutableFields(&target.TLS, fieldPrefix+"tls."); len(list) > 0 {
result = append(result, list...)
}
return result
}

View file

@ -1,30 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
// EndpointStatus contains the status of either the source or destination endpoint.
type EndpointStatus struct {
// Databases holds the replication status of all databases from the point of view of this endpoint.
// List is ordered by name of the database.
Databases []DatabaseStatus `json:"databases,omitempty"`
}

View file

@ -1,72 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
"github.com/pkg/errors"
)
// EndpointTLSSpec contains the specification regarding the TLS connection to the syncmasters
// in either source or destination endpoint.
type EndpointTLSSpec struct {
// CASecretName holds the name of a Secret containing a ca.crt public key for TLS validation.
CASecretName *string `json:"caSecretName,omitempty"`
}
// GetCASecretName returns the value of caSecretName.
func (s EndpointTLSSpec) GetCASecretName() string {
return util.StringOrDefault(s.CASecretName)
}
// Validate the given spec, returning an error on validation
// problems or nil if all ok.
func (s EndpointTLSSpec) Validate(caSecretNameRequired bool) error {
if err := k8sutil.ValidateOptionalResourceName(s.GetCASecretName()); err != nil {
return maskAny(err)
}
if caSecretNameRequired && s.GetCASecretName() == "" {
return maskAny(errors.Wrapf(ValidationError, "Provide a caSecretName"))
}
return nil
}
// SetDefaults fills empty field with default values.
func (s *EndpointTLSSpec) SetDefaults() {
}
// SetDefaultsFrom fills empty field with default values from the given source.
func (s *EndpointTLSSpec) SetDefaultsFrom(source EndpointTLSSpec) {
if s.CASecretName == nil {
s.CASecretName = util.NewStringOrNil(source.CASecretName)
}
}
// ResetImmutableFields replaces all immutable fields in the given target with values from the source spec.
// It returns a list of fields that have been reset.
// Field names are relative to `spec.`.
func (s EndpointTLSSpec) ResetImmutableFields(target *EndpointTLSSpec, fieldPrefix string) []string {
var result []string
return result
}

View file

@ -1,37 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import "github.com/pkg/errors"
var (
// ValidationError indicates a validation failure
ValidationError = errors.New("validation failed")
maskAny = errors.WithStack
)
// IsValidation return true when the given error is or is caused by a ValidationError.
func IsValidation(err error) bool {
return errors.Cause(err) == ValidationError
}

View file

@ -1,57 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"github.com/arangodb/kube-arangodb/pkg/apis/replication"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
const (
ArangoDeploymentReplicationVersion = "v1alpha"
)
var (
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
AddToScheme = SchemeBuilder.AddToScheme
SchemeGroupVersion = schema.GroupVersion{Group: replication.ArangoDeploymentReplicationGroupName,
Version: ArangoDeploymentReplicationVersion}
)
// Resource gets an ArangoCluster GroupResource for a specified resource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
// addKnownTypes adds the set of types defined in this package to the supplied scheme.
func addKnownTypes(s *runtime.Scheme) error {
s.AddKnownTypes(SchemeGroupVersion,
&ArangoDeploymentReplication{},
&ArangoDeploymentReplicationList{},
)
metav1.AddToGroupVersion(s, SchemeGroupVersion)
return nil
}

View file

@ -1,64 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
import (
"github.com/arangodb/kube-arangodb/pkg/apis/replication"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ArangoDeploymentReplicationList is a list of ArangoDB deployment replications.
type ArangoDeploymentReplicationList struct {
metav1.TypeMeta `json:",inline"`
// Standard list metadata
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
metav1.ListMeta `json:"metadata,omitempty"`
Items []ArangoDeploymentReplication `json:"items"`
}
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ArangoDeploymentReplication contains the entire Kubernetes info for an ArangoDB
// local storage provider.
type ArangoDeploymentReplication struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec DeploymentReplicationSpec `json:"spec"`
Status DeploymentReplicationStatus `json:"status"`
}
// AsOwner creates an OwnerReference for the given replication
func (d *ArangoDeploymentReplication) AsOwner() metav1.OwnerReference {
trueVar := true
return metav1.OwnerReference{
APIVersion: SchemeGroupVersion.String(),
Kind: replication.ArangoDeploymentReplicationResourceKind,
Name: d.Name,
UID: d.UID,
Controller: &trueVar,
BlockOwnerDeletion: &trueVar,
}
}

View file

@ -1,39 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
// DeploymentReplicationPhase is a strongly typed lifetime phase of a deployment replication
type DeploymentReplicationPhase string
const (
// DeploymentReplicationPhaseNone indicates that the phase is not set yet
DeploymentReplicationPhaseNone DeploymentReplicationPhase = ""
// DeploymentReplicationPhaseFailed indicates that a deployment replication is in a failed state
// from which automatic recovery is impossible. Inspect `Reason` for more info.
DeploymentReplicationPhaseFailed DeploymentReplicationPhase = "Failed"
)
// IsFailed returns true if given state is DeploymentStateFailed
func (cs DeploymentReplicationPhase) IsFailed() bool {
return cs == DeploymentReplicationPhaseFailed
}

View file

@ -1,68 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
// DeploymentReplicationSpec contains the specification part of
// an ArangoDeploymentReplication.
type DeploymentReplicationSpec struct {
Source EndpointSpec `json:"source"`
Destination EndpointSpec `json:"destination"`
}
// Validate the given spec, returning an error on validation
// problems or nil if all ok.
func (s DeploymentReplicationSpec) Validate() error {
if err := s.Source.Validate(true); err != nil {
return maskAny(err)
}
if err := s.Destination.Validate(false); err != nil {
return maskAny(err)
}
return nil
}
// SetDefaults fills empty field with default values.
func (s *DeploymentReplicationSpec) SetDefaults() {
s.Source.SetDefaults()
s.Destination.SetDefaults()
}
// SetDefaultsFrom fills empty field with default values from the given source.
func (s *DeploymentReplicationSpec) SetDefaultsFrom(source DeploymentReplicationSpec) {
s.Source.SetDefaultsFrom(source.Source)
s.Destination.SetDefaultsFrom(source.Destination)
}
// ResetImmutableFields replaces all immutable fields in the given target with values from the source spec.
// It returns a list of fields that have been reset.
// Field names are relative to `spec.`.
func (s DeploymentReplicationSpec) ResetImmutableFields(target *DeploymentReplicationSpec) []string {
var result []string
if list := s.Source.ResetImmutableFields(&target.Source, "source."); len(list) > 0 {
result = append(result, list...)
}
if list := s.Destination.ResetImmutableFields(&target.Destination, "destination."); len(list) > 0 {
result = append(result, list...)
}
return result
}

View file

@ -1,44 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
// DeploymentReplicationStatus contains the status part of
// an ArangoDeploymentReplication.
type DeploymentReplicationStatus struct {
// Phase holds the current lifetime phase of the deployment replication
Phase DeploymentReplicationPhase `json:"phase,omitempty"`
// Reason contains a human readable reason for reaching the current phase (can be empty)
Reason string `json:"reason,omitempty"` // Reason for current phase
// Conditions specific to the entire deployment replication
Conditions ConditionList `json:"conditions,omitempty"`
// Source contains the detailed status of the source endpoint
Source EndpointStatus `json:"source"`
// Destination contains the detailed status of the destination endpoint
Destination EndpointStatus `json:"destination"`
// CancelFailures records the number of times that the configuration was canceled
// which resulted in an error.
CancelFailures int `json:"cancel-failures,omitempty"`
}

View file

@ -1,28 +0,0 @@
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Author Ewout Prangsma
//
package v1alpha
// ShardStatus contains the status of a single shard.
type ShardStatus struct {
Status string `json:"status"`
}

View file

@ -1,331 +0,0 @@
// +build !ignore_autogenerated
//
// DISCLAIMER
//
// Copyright 2018 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
//
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1alpha
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoDeploymentReplication) DeepCopyInto(out *ArangoDeploymentReplication) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoDeploymentReplication.
func (in *ArangoDeploymentReplication) DeepCopy() *ArangoDeploymentReplication {
if in == nil {
return nil
}
out := new(ArangoDeploymentReplication)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ArangoDeploymentReplication) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoDeploymentReplicationList) DeepCopyInto(out *ArangoDeploymentReplicationList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]ArangoDeploymentReplication, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoDeploymentReplicationList.
func (in *ArangoDeploymentReplicationList) DeepCopy() *ArangoDeploymentReplicationList {
if in == nil {
return nil
}
out := new(ArangoDeploymentReplicationList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ArangoDeploymentReplicationList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CollectionStatus) DeepCopyInto(out *CollectionStatus) {
*out = *in
if in.Shards != nil {
in, out := &in.Shards, &out.Shards
*out = make([]ShardStatus, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CollectionStatus.
func (in *CollectionStatus) DeepCopy() *CollectionStatus {
if in == nil {
return nil
}
out := new(CollectionStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Condition) DeepCopyInto(out *Condition) {
*out = *in
in.LastUpdateTime.DeepCopyInto(&out.LastUpdateTime)
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition.
func (in *Condition) DeepCopy() *Condition {
if in == nil {
return nil
}
out := new(Condition)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in ConditionList) DeepCopyInto(out *ConditionList) {
{
in := &in
*out = make(ConditionList, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
return
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConditionList.
func (in ConditionList) DeepCopy() ConditionList {
if in == nil {
return nil
}
out := new(ConditionList)
in.DeepCopyInto(out)
return *out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DatabaseStatus) DeepCopyInto(out *DatabaseStatus) {
*out = *in
if in.Collections != nil {
in, out := &in.Collections, &out.Collections
*out = make([]CollectionStatus, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatabaseStatus.
func (in *DatabaseStatus) DeepCopy() *DatabaseStatus {
if in == nil {
return nil
}
out := new(DatabaseStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DeploymentReplicationSpec) DeepCopyInto(out *DeploymentReplicationSpec) {
*out = *in
in.Source.DeepCopyInto(&out.Source)
in.Destination.DeepCopyInto(&out.Destination)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentReplicationSpec.
func (in *DeploymentReplicationSpec) DeepCopy() *DeploymentReplicationSpec {
if in == nil {
return nil
}
out := new(DeploymentReplicationSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DeploymentReplicationStatus) DeepCopyInto(out *DeploymentReplicationStatus) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make(ConditionList, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
in.Source.DeepCopyInto(&out.Source)
in.Destination.DeepCopyInto(&out.Destination)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentReplicationStatus.
func (in *DeploymentReplicationStatus) DeepCopy() *DeploymentReplicationStatus {
if in == nil {
return nil
}
out := new(DeploymentReplicationStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *EndpointAuthenticationSpec) DeepCopyInto(out *EndpointAuthenticationSpec) {
*out = *in
if in.KeyfileSecretName != nil {
in, out := &in.KeyfileSecretName, &out.KeyfileSecretName
*out = new(string)
**out = **in
}
if in.UserSecretName != nil {
in, out := &in.UserSecretName, &out.UserSecretName
*out = new(string)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndpointAuthenticationSpec.
func (in *EndpointAuthenticationSpec) DeepCopy() *EndpointAuthenticationSpec {
if in == nil {
return nil
}
out := new(EndpointAuthenticationSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *EndpointSpec) DeepCopyInto(out *EndpointSpec) {
*out = *in
if in.DeploymentName != nil {
in, out := &in.DeploymentName, &out.DeploymentName
*out = new(string)
**out = **in
}
if in.MasterEndpoint != nil {
in, out := &in.MasterEndpoint, &out.MasterEndpoint
*out = make([]string, len(*in))
copy(*out, *in)
}
in.Authentication.DeepCopyInto(&out.Authentication)
in.TLS.DeepCopyInto(&out.TLS)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndpointSpec.
func (in *EndpointSpec) DeepCopy() *EndpointSpec {
if in == nil {
return nil
}
out := new(EndpointSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *EndpointStatus) DeepCopyInto(out *EndpointStatus) {
*out = *in
if in.Databases != nil {
in, out := &in.Databases, &out.Databases
*out = make([]DatabaseStatus, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndpointStatus.
func (in *EndpointStatus) DeepCopy() *EndpointStatus {
if in == nil {
return nil
}
out := new(EndpointStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *EndpointTLSSpec) DeepCopyInto(out *EndpointTLSSpec) {
*out = *in
if in.CASecretName != nil {
in, out := &in.CASecretName, &out.CASecretName
*out = new(string)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndpointTLSSpec.
func (in *EndpointTLSSpec) DeepCopy() *EndpointTLSSpec {
if in == nil {
return nil
}
out := new(EndpointTLSSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ShardStatus) DeepCopyInto(out *ShardStatus) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ShardStatus.
func (in *ShardStatus) DeepCopy() *ShardStatus {
if in == nil {
return nil
}
out := new(ShardStatus)
in.DeepCopyInto(out)
return out
}

View file

@ -24,11 +24,8 @@ package versioned
import (
backupv1 "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/backup/v1"
backupv1alpha "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/backup/v1alpha"
databasev1 "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/deployment/v1"
databasev1alpha "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/deployment/v1alpha"
replicationv1 "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/replication/v1"
replicationv1alpha "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/replication/v1alpha"
storagev1alpha "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/storage/v1alpha"
discovery "k8s.io/client-go/discovery"
rest "k8s.io/client-go/rest"
@ -37,11 +34,8 @@ import (
type Interface interface {
Discovery() discovery.DiscoveryInterface
BackupV1alpha() backupv1alpha.BackupV1alphaInterface
BackupV1() backupv1.BackupV1Interface
DatabaseV1alpha() databasev1alpha.DatabaseV1alphaInterface
DatabaseV1() databasev1.DatabaseV1Interface
ReplicationV1alpha() replicationv1alpha.ReplicationV1alphaInterface
ReplicationV1() replicationv1.ReplicationV1Interface
StorageV1alpha() storagev1alpha.StorageV1alphaInterface
}
@ -50,18 +44,10 @@ type Interface interface {
// version included in a Clientset.
type Clientset struct {
*discovery.DiscoveryClient
backupV1alpha *backupv1alpha.BackupV1alphaClient
backupV1 *backupv1.BackupV1Client
databaseV1alpha *databasev1alpha.DatabaseV1alphaClient
databaseV1 *databasev1.DatabaseV1Client
replicationV1alpha *replicationv1alpha.ReplicationV1alphaClient
replicationV1 *replicationv1.ReplicationV1Client
storageV1alpha *storagev1alpha.StorageV1alphaClient
}
// BackupV1alpha retrieves the BackupV1alphaClient
func (c *Clientset) BackupV1alpha() backupv1alpha.BackupV1alphaInterface {
return c.backupV1alpha
backupV1 *backupv1.BackupV1Client
databaseV1 *databasev1.DatabaseV1Client
replicationV1 *replicationv1.ReplicationV1Client
storageV1alpha *storagev1alpha.StorageV1alphaClient
}
// BackupV1 retrieves the BackupV1Client
@ -69,21 +55,11 @@ func (c *Clientset) BackupV1() backupv1.BackupV1Interface {
return c.backupV1
}
// DatabaseV1alpha retrieves the DatabaseV1alphaClient
func (c *Clientset) DatabaseV1alpha() databasev1alpha.DatabaseV1alphaInterface {
return c.databaseV1alpha
}
// DatabaseV1 retrieves the DatabaseV1Client
func (c *Clientset) DatabaseV1() databasev1.DatabaseV1Interface {
return c.databaseV1
}
// ReplicationV1alpha retrieves the ReplicationV1alphaClient
func (c *Clientset) ReplicationV1alpha() replicationv1alpha.ReplicationV1alphaInterface {
return c.replicationV1alpha
}
// ReplicationV1 retrieves the ReplicationV1Client
func (c *Clientset) ReplicationV1() replicationv1.ReplicationV1Interface {
return c.replicationV1
@ -110,26 +86,14 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
}
var cs Clientset
var err error
cs.backupV1alpha, err = backupv1alpha.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
cs.backupV1, err = backupv1.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
cs.databaseV1alpha, err = databasev1alpha.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
cs.databaseV1, err = databasev1.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
cs.replicationV1alpha, err = replicationv1alpha.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
cs.replicationV1, err = replicationv1.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
@ -150,11 +114,8 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
// panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *Clientset {
var cs Clientset
cs.backupV1alpha = backupv1alpha.NewForConfigOrDie(c)
cs.backupV1 = backupv1.NewForConfigOrDie(c)
cs.databaseV1alpha = databasev1alpha.NewForConfigOrDie(c)
cs.databaseV1 = databasev1.NewForConfigOrDie(c)
cs.replicationV1alpha = replicationv1alpha.NewForConfigOrDie(c)
cs.replicationV1 = replicationv1.NewForConfigOrDie(c)
cs.storageV1alpha = storagev1alpha.NewForConfigOrDie(c)
@ -165,11 +126,8 @@ func NewForConfigOrDie(c *rest.Config) *Clientset {
// New creates a new Clientset for the given RESTClient.
func New(c rest.Interface) *Clientset {
var cs Clientset
cs.backupV1alpha = backupv1alpha.New(c)
cs.backupV1 = backupv1.New(c)
cs.databaseV1alpha = databasev1alpha.New(c)
cs.databaseV1 = databasev1.New(c)
cs.replicationV1alpha = replicationv1alpha.New(c)
cs.replicationV1 = replicationv1.New(c)
cs.storageV1alpha = storagev1alpha.New(c)

View file

@ -26,16 +26,10 @@ import (
clientset "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned"
backupv1 "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/backup/v1"
fakebackupv1 "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/backup/v1/fake"
backupv1alpha "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/backup/v1alpha"
fakebackupv1alpha "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/backup/v1alpha/fake"
databasev1 "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/deployment/v1"
fakedatabasev1 "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/deployment/v1/fake"
databasev1alpha "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/deployment/v1alpha"
fakedatabasev1alpha "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/deployment/v1alpha/fake"
replicationv1 "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/replication/v1"
fakereplicationv1 "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/replication/v1/fake"
replicationv1alpha "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/replication/v1alpha"
fakereplicationv1alpha "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/replication/v1alpha/fake"
storagev1alpha "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/storage/v1alpha"
fakestoragev1alpha "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/typed/storage/v1alpha/fake"
"k8s.io/apimachinery/pkg/runtime"
@ -87,31 +81,16 @@ func (c *Clientset) Discovery() discovery.DiscoveryInterface {
var _ clientset.Interface = &Clientset{}
// BackupV1alpha retrieves the BackupV1alphaClient
func (c *Clientset) BackupV1alpha() backupv1alpha.BackupV1alphaInterface {
return &fakebackupv1alpha.FakeBackupV1alpha{Fake: &c.Fake}
}
// BackupV1 retrieves the BackupV1Client
func (c *Clientset) BackupV1() backupv1.BackupV1Interface {
return &fakebackupv1.FakeBackupV1{Fake: &c.Fake}
}
// DatabaseV1alpha retrieves the DatabaseV1alphaClient
func (c *Clientset) DatabaseV1alpha() databasev1alpha.DatabaseV1alphaInterface {
return &fakedatabasev1alpha.FakeDatabaseV1alpha{Fake: &c.Fake}
}
// DatabaseV1 retrieves the DatabaseV1Client
func (c *Clientset) DatabaseV1() databasev1.DatabaseV1Interface {
return &fakedatabasev1.FakeDatabaseV1{Fake: &c.Fake}
}
// ReplicationV1alpha retrieves the ReplicationV1alphaClient
func (c *Clientset) ReplicationV1alpha() replicationv1alpha.ReplicationV1alphaInterface {
return &fakereplicationv1alpha.FakeReplicationV1alpha{Fake: &c.Fake}
}
// ReplicationV1 retrieves the ReplicationV1Client
func (c *Clientset) ReplicationV1() replicationv1.ReplicationV1Interface {
return &fakereplicationv1.FakeReplicationV1{Fake: &c.Fake}

View file

@ -24,11 +24,8 @@ package fake
import (
backupv1 "github.com/arangodb/kube-arangodb/pkg/apis/backup/v1"
backupv1alpha "github.com/arangodb/kube-arangodb/pkg/apis/backup/v1alpha"
databasev1 "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
databasev1alpha "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha"
replicationv1 "github.com/arangodb/kube-arangodb/pkg/apis/replication/v1"
replicationv1alpha "github.com/arangodb/kube-arangodb/pkg/apis/replication/v1alpha"
storagev1alpha "github.com/arangodb/kube-arangodb/pkg/apis/storage/v1alpha"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
@ -41,11 +38,8 @@ var scheme = runtime.NewScheme()
var codecs = serializer.NewCodecFactory(scheme)
var parameterCodec = runtime.NewParameterCodec(scheme)
var localSchemeBuilder = runtime.SchemeBuilder{
backupv1alpha.AddToScheme,
backupv1.AddToScheme,
databasev1alpha.AddToScheme,
databasev1.AddToScheme,
replicationv1alpha.AddToScheme,
replicationv1.AddToScheme,
storagev1alpha.AddToScheme,
}

View file

@ -24,11 +24,8 @@ package scheme
import (
backupv1 "github.com/arangodb/kube-arangodb/pkg/apis/backup/v1"
backupv1alpha "github.com/arangodb/kube-arangodb/pkg/apis/backup/v1alpha"
databasev1 "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
databasev1alpha "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha"
replicationv1 "github.com/arangodb/kube-arangodb/pkg/apis/replication/v1"
replicationv1alpha "github.com/arangodb/kube-arangodb/pkg/apis/replication/v1alpha"
storagev1alpha "github.com/arangodb/kube-arangodb/pkg/apis/storage/v1alpha"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
@ -41,11 +38,8 @@ var Scheme = runtime.NewScheme()
var Codecs = serializer.NewCodecFactory(Scheme)
var ParameterCodec = runtime.NewParameterCodec(Scheme)
var localSchemeBuilder = runtime.SchemeBuilder{
backupv1alpha.AddToScheme,
backupv1.AddToScheme,
databasev1alpha.AddToScheme,
databasev1.AddToScheme,
replicationv1alpha.AddToScheme,
replicationv1.AddToScheme,
storagev1alpha.AddToScheme,
}

View file

@ -24,14 +24,11 @@ package backup
import (
v1 "github.com/arangodb/kube-arangodb/pkg/generated/informers/externalversions/backup/v1"
v1alpha "github.com/arangodb/kube-arangodb/pkg/generated/informers/externalversions/backup/v1alpha"
internalinterfaces "github.com/arangodb/kube-arangodb/pkg/generated/informers/externalversions/internalinterfaces"
)
// Interface provides access to each of this group's versions.
type Interface interface {
// V1alpha provides access to shared informers for resources in V1alpha.
V1alpha() v1alpha.Interface
// V1 provides access to shared informers for resources in V1.
V1() v1.Interface
}
@ -47,11 +44,6 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// V1alpha returns a new v1alpha.Interface.
func (g *group) V1alpha() v1alpha.Interface {
return v1alpha.New(g.factory, g.namespace, g.tweakListOptions)
}
// V1 returns a new v1.Interface.
func (g *group) V1() v1.Interface {
return v1.New(g.factory, g.namespace, g.tweakListOptions)

View file

@ -24,14 +24,11 @@ package database
import (
v1 "github.com/arangodb/kube-arangodb/pkg/generated/informers/externalversions/deployment/v1"
v1alpha "github.com/arangodb/kube-arangodb/pkg/generated/informers/externalversions/deployment/v1alpha"
internalinterfaces "github.com/arangodb/kube-arangodb/pkg/generated/informers/externalversions/internalinterfaces"
)
// Interface provides access to each of this group's versions.
type Interface interface {
// V1alpha provides access to shared informers for resources in V1alpha.
V1alpha() v1alpha.Interface
// V1 provides access to shared informers for resources in V1.
V1() v1.Interface
}
@ -47,11 +44,6 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// V1alpha returns a new v1alpha.Interface.
func (g *group) V1alpha() v1alpha.Interface {
return v1alpha.New(g.factory, g.namespace, g.tweakListOptions)
}
// V1 returns a new v1.Interface.
func (g *group) V1() v1.Interface {
return v1.New(g.factory, g.namespace, g.tweakListOptions)

View file

@ -26,12 +26,9 @@ import (
"fmt"
v1 "github.com/arangodb/kube-arangodb/pkg/apis/backup/v1"
v1alpha "github.com/arangodb/kube-arangodb/pkg/apis/backup/v1alpha"
deploymentv1 "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
deploymentv1alpha "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha"
replicationv1 "github.com/arangodb/kube-arangodb/pkg/apis/replication/v1"
replicationv1alpha "github.com/arangodb/kube-arangodb/pkg/apis/replication/v1alpha"
storagev1alpha "github.com/arangodb/kube-arangodb/pkg/apis/storage/v1alpha"
v1alpha "github.com/arangodb/kube-arangodb/pkg/apis/storage/v1alpha"
schema "k8s.io/apimachinery/pkg/runtime/schema"
cache "k8s.io/client-go/tools/cache"
)
@ -68,30 +65,16 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
case v1.SchemeGroupVersion.WithResource("arangobackuppolicies"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Backup().V1().ArangoBackupPolicies().Informer()}, nil
// Group=backup.arangodb.com, Version=v1alpha
case v1alpha.SchemeGroupVersion.WithResource("arangobackups"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Backup().V1alpha().ArangoBackups().Informer()}, nil
case v1alpha.SchemeGroupVersion.WithResource("arangobackuppolicies"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Backup().V1alpha().ArangoBackupPolicies().Informer()}, nil
// Group=database.arangodb.com, Version=v1
case deploymentv1.SchemeGroupVersion.WithResource("arangodeployments"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Database().V1().ArangoDeployments().Informer()}, nil
// Group=database.arangodb.com, Version=v1alpha
case deploymentv1alpha.SchemeGroupVersion.WithResource("arangodeployments"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Database().V1alpha().ArangoDeployments().Informer()}, nil
// Group=replication.database.arangodb.com, Version=v1
case replicationv1.SchemeGroupVersion.WithResource("arangodeploymentreplications"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Replication().V1().ArangoDeploymentReplications().Informer()}, nil
// Group=replication.database.arangodb.com, Version=v1alpha
case replicationv1alpha.SchemeGroupVersion.WithResource("arangodeploymentreplications"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Replication().V1alpha().ArangoDeploymentReplications().Informer()}, nil
// Group=storage.arangodb.com, Version=v1alpha
case storagev1alpha.SchemeGroupVersion.WithResource("arangolocalstorages"):
case v1alpha.SchemeGroupVersion.WithResource("arangolocalstorages"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Storage().V1alpha().ArangoLocalStorages().Informer()}, nil
}

View file

@ -25,13 +25,10 @@ package replication
import (
internalinterfaces "github.com/arangodb/kube-arangodb/pkg/generated/informers/externalversions/internalinterfaces"
v1 "github.com/arangodb/kube-arangodb/pkg/generated/informers/externalversions/replication/v1"
v1alpha "github.com/arangodb/kube-arangodb/pkg/generated/informers/externalversions/replication/v1alpha"
)
// Interface provides access to each of this group's versions.
type Interface interface {
// V1alpha provides access to shared informers for resources in V1alpha.
V1alpha() v1alpha.Interface
// V1 provides access to shared informers for resources in V1.
V1() v1.Interface
}
@ -47,11 +44,6 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// V1alpha returns a new v1alpha.Interface.
func (g *group) V1alpha() v1alpha.Interface {
return v1alpha.New(g.factory, g.namespace, g.tweakListOptions)
}
// V1 returns a new v1.Interface.
func (g *group) V1() v1.Interface {
return v1.New(g.factory, g.namespace, g.tweakListOptions)

View file

@ -33,7 +33,7 @@ import (
"k8s.io/apimachinery/pkg/util/intstr"
deplv1alpha "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha"
deplv1 "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
extclient "github.com/arangodb/kube-arangodb/pkg/client"
acli "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned"
"github.com/arangodb/kube-arangodb/pkg/util"
@ -330,19 +330,19 @@ func createArangoDeployment(cli acli.Interface, ns, deplname, arangoimage string
}
}
depl := deplv1alpha.ArangoDeployment{
depl := deplv1.ArangoDeployment{
ObjectMeta: metav1.ObjectMeta{
Name: deplname,
},
Spec: deplv1alpha.DeploymentSpec{
Spec: deplv1.DeploymentSpec{
Image: util.NewString(arangoimage),
Coordinators: deplv1alpha.ServerGroupSpec{
Coordinators: deplv1.ServerGroupSpec{
Count: util.NewInt(rebootOptions.Coordinators),
},
Agents: deplv1alpha.ServerGroupSpec{
Agents: deplv1.ServerGroupSpec{
Count: util.NewInt(len(agnt)),
},
DBServers: deplv1alpha.ServerGroupSpec{
DBServers: deplv1.ServerGroupSpec{
Count: util.NewInt(len(prmr)),
},
},
@ -353,22 +353,22 @@ func createArangoDeployment(cli acli.Interface, ns, deplname, arangoimage string
}
for _, info := range agnt {
depl.Status.Members.Agents = append(depl.Status.Members.Agents, deplv1alpha.MemberStatus{
depl.Status.Members.Agents = append(depl.Status.Members.Agents, deplv1.MemberStatus{
ID: info.UUID,
PersistentVolumeClaimName: info.Claim,
PodName: k8sutil.CreatePodName(deplname, deplv1alpha.ServerGroupAgents.AsRole(), info.UUID, "-rbt"),
PodName: k8sutil.CreatePodName(deplname, deplv1.ServerGroupAgents.AsRole(), info.UUID, "-rbt"),
})
}
for _, info := range prmr {
depl.Status.Members.DBServers = append(depl.Status.Members.DBServers, deplv1alpha.MemberStatus{
depl.Status.Members.DBServers = append(depl.Status.Members.DBServers, deplv1.MemberStatus{
ID: info.UUID,
PersistentVolumeClaimName: info.Claim,
PodName: k8sutil.CreatePodName(deplname, deplv1alpha.ServerGroupDBServers.AsRole(), info.UUID, "-rbt"),
PodName: k8sutil.CreatePodName(deplname, deplv1.ServerGroupDBServers.AsRole(), info.UUID, "-rbt"),
})
}
if _, err := cli.DatabaseV1alpha().ArangoDeployments(ns).Create(&depl); err != nil {
if _, err := cli.DatabaseV1().ArangoDeployments(ns).Create(&depl); err != nil {
return errors.Wrap(err, "failed to create ArangoDeployment")
}

View file

@ -1,7 +1,7 @@
//
// DISCLAIMER
//
// Copyright 2018 ArangoDB GmbH, Cologne, Germany
// Copyright 2020 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.
@ -20,13 +20,23 @@
// Author Adam Janikowski
//
package v1alpha
package main
import (
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
"fmt"
"github.com/spf13/cobra"
"runtime"
)
type ArangoBackupPolicyStatus struct {
Scheduled meta.Time `json:"scheduled,omitempty"`
Message string `json:"message,omitempty"`
func init() {
cmdMain.AddCommand(cmdVersion)
}
var cmdVersion = &cobra.Command{
Use: "version",
Run: versionRun,
}
func versionRun(cmd *cobra.Command, args []string) {
println(fmt.Sprintf("Version: %s, Build: %s, Go: %s", projectVersion, projectBuild, runtime.Version()))
}