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:
parent
e7d5d8f3a9
commit
3254e2f789
99 changed files with 44 additions and 9263 deletions
|
@ -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
|
||||
|
|
2
Makefile
2
Makefile
|
@ -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
1
go.mod
|
@ -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
5
go.sum
|
@ -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=
|
||||
|
|
|
@ -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"`
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -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"`
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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"`
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
}
|
426
pkg/apis/backup/v1alpha/zz_generated.deepcopy.go
generated
426
pkg/apis/backup/v1alpha/zz_generated.deepcopy.go
generated
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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))
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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())
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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())
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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{}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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())
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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())
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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))
|
||||
}
|
|
@ -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)))
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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())
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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))
|
||||
}
|
|
@ -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())
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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())
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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())
|
||||
}
|
1029
pkg/apis/deployment/v1alpha/zz_generated.deepcopy.go
generated
1029
pkg/apis/deployment/v1alpha/zz_generated.deepcopy.go
generated
File diff suppressed because it is too large
Load diff
|
@ -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"`
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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))
|
||||
}
|
|
@ -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"`
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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"`
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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"`
|
||||
}
|
|
@ -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"`
|
||||
}
|
331
pkg/apis/replication/v1alpha/zz_generated.deepcopy.go
generated
331
pkg/apis/replication/v1alpha/zz_generated.deepcopy.go
generated
|
@ -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
|
||||
}
|
50
pkg/generated/clientset/versioned/clientset.go
generated
50
pkg/generated/clientset/versioned/clientset.go
generated
|
@ -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)
|
||||
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
21
pkg/generated/informers/externalversions/generic.go
generated
21
pkg/generated/informers/externalversions/generic.go
generated
|
@ -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
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
22
reboot.go
22
reboot.go
|
@ -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")
|
||||
}
|
||||
|
||||
|
|
|
@ -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()))
|
||||
}
|
Loading…
Reference in a new issue