mirror of
https://github.com/arangodb/kube-arangodb.git
synced 2024-12-14 11:57:37 +00:00
[Feature] Add Maintenance Mode support (#623)
This commit is contained in:
parent
7a8be98fa3
commit
9b5f145bc2
26 changed files with 619 additions and 64 deletions
|
@ -1,6 +1,7 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
## [master](https://github.com/arangodb/kube-arangodb/tree/master) (N/A)
|
## [master](https://github.com/arangodb/kube-arangodb/tree/master) (N/A)
|
||||||
|
- Add Operator Maintenance Management feature
|
||||||
|
|
||||||
## [1.0.6](https://github.com/arangodb/kube-arangodb/tree/1.0.6) (2020-08-19)
|
## [1.0.6](https://github.com/arangodb/kube-arangodb/tree/1.0.6) (2020-08-19)
|
||||||
- Add Operator Namespaced mode (Alpha)
|
- Add Operator Namespaced mode (Alpha)
|
||||||
|
|
39
README.md
39
README.md
|
@ -60,25 +60,26 @@ covers individual newer features separately.
|
||||||
|
|
||||||
Feature-wise production readiness table:
|
Feature-wise production readiness table:
|
||||||
|
|
||||||
| Feature | Operator Version | ArangoDB Version | ArangoDB Edition | State | Enabled | Flag | Remarks |
|
| Feature | Operator Version | ArangoDB Version | ArangoDB Edition | State | Enabled | Flag | Remarks |
|
||||||
|---------------------------------|------------------|------------------|-----------------------|------------|---------|------------------------------------------|--------------------------------------------------------------------------|
|
|-----------------------------------------|------------------|------------------|-----------------------|------------|---------|------------------------------------------|--------------------------------------------------------------------------|
|
||||||
| Pod Disruption Budgets | 0.3.10 | Any | Community, Enterprise | Alpha | True | N/A | N/A |
|
| Pod Disruption Budgets | 0.3.10 | Any | Community, Enterprise | Alpha | True | N/A | N/A |
|
||||||
| Pod Disruption Budgets | 0.3.11 | Any | Community, Enterprise | Production | True | N/A | N/A |
|
| Pod Disruption Budgets | 0.3.11 | Any | Community, Enterprise | Production | True | N/A | N/A |
|
||||||
| Volume Resizing | 0.3.10 | Any | Community, Enterprise | Alpha | True | N/A | N/A |
|
| Volume Resizing | 0.3.10 | Any | Community, Enterprise | Alpha | True | N/A | N/A |
|
||||||
| Volume Resizing | 0.3.11 | Any | Community, Enterprise | Production | True | N/A | N/A |
|
| Volume Resizing | 0.3.11 | Any | Community, Enterprise | Production | True | N/A | N/A |
|
||||||
| Disabling of liveness probes | 0.3.10 | Any | Community, Enterprise | Alpha | True | N/A | N/A |
|
| Disabling of liveness probes | 0.3.10 | Any | Community, Enterprise | Alpha | True | N/A | N/A |
|
||||||
| Disabling of liveness probes | 0.3.11 | Any | Community, Enterprise | Production | True | N/A | N/A |
|
| Disabling of liveness probes | 0.3.11 | Any | Community, Enterprise | Production | True | N/A | N/A |
|
||||||
| Volume Claim Templates | 0.3.11 | Any | Community, Enterprise | Alpha | True | N/A | N/A |
|
| Volume Claim Templates | 0.3.11 | Any | Community, Enterprise | Alpha | True | N/A | N/A |
|
||||||
| Volume Claim Templates | 1.0.0 | Any | Community, Enterprise | Production | True | N/A | N/A |
|
| Volume Claim Templates | 1.0.0 | Any | Community, Enterprise | Production | True | N/A | N/A |
|
||||||
| Prometheus Metrics Exporter | 0.3.11 | Any | Community, Enterprise | Alpha | True | N/A | Prometheus required |
|
| Prometheus Metrics Exporter | 0.3.11 | Any | Community, Enterprise | Alpha | True | N/A | Prometheus required |
|
||||||
| Prometheus Metrics Exporter | 1.0.0 | Any | Community, Enterprise | Production | True | N/A | Prometheus required |
|
| Prometheus Metrics Exporter | 1.0.0 | Any | Community, Enterprise | Production | True | N/A | Prometheus required |
|
||||||
| Sidecar Containers | 0.3.11 | Any | Community, Enterprise | Alpha | True | N/A | N/A |
|
| Sidecar Containers | 0.3.11 | Any | Community, Enterprise | Alpha | True | N/A | N/A |
|
||||||
| Sidecar Containers | 1.0.0 | Any | Community, Enterprise | Production | True | N/A | N/A |
|
| Sidecar Containers | 1.0.0 | Any | Community, Enterprise | Production | True | N/A | N/A |
|
||||||
| Operator Single Mode | 1.0.4 | Any | Community, Enterprise | Production | False | --mode.single | Only 1 instance of Operator allowed in namespace when feature is enabled |
|
| Operator Single Mode | 1.0.4 | Any | Community, Enterprise | Production | False | --mode.single | Only 1 instance of Operator allowed in namespace when feature is enabled |
|
||||||
| TLS SNI Support | 1.0.3 | >= 3.7.0 | Enterprise | Production | True | --deployment.feature.tls-sni | N/A |
|
| TLS SNI Support | 1.0.3 | >= 3.7.0 | Enterprise | Production | True | --deployment.feature.tls-sni | N/A |
|
||||||
| TLS Runtime Rotation Support | 1.0.4 | > 3.7.0 | Enterprise | Alpha | False | --deployment.feature.tls-rotation | N/A |
|
| TLS Runtime Rotation Support | 1.0.4 | > 3.7.0 | Enterprise | Alpha | False | --deployment.feature.tls-rotation | N/A |
|
||||||
| JWT Rotation Support | 1.0.4 | > 3.7.0 | Enterprise | Alpha | False | --deployment.feature.jwt-rotation | N/A |
|
| JWT Rotation Support | 1.0.4 | > 3.7.0 | Enterprise | Alpha | False | --deployment.feature.jwt-rotation | N/A |
|
||||||
| Encryption Key Rotation Support | 1.0.4 | > 3.7.0 | Enterprise | Alpha | False | --deployment.feature.encryption-rotation | N/A |
|
| Encryption Key Rotation Support | 1.0.4 | > 3.7.0 | Enterprise | Alpha | False | --deployment.feature.encryption-rotation | N/A |
|
||||||
|
| Operator Maintenance Management Support | 1.0.7 | >= 3.5.0 | Community, Enterprise | Alpha | False | --deployment.feature.maintenance | N/A |
|
||||||
|
|
||||||
## Release notes for 0.3.16
|
## Release notes for 0.3.16
|
||||||
|
|
||||||
|
|
35
pkg/apis/deployment/v1/database_spec.go
Normal file
35
pkg/apis/deployment/v1/database_spec.go
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
//
|
||||||
|
// DISCLAIMER
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
// 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 v1
|
||||||
|
|
||||||
|
type DatabaseSpec struct {
|
||||||
|
Maintenance *bool `json:"maintenance,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *DatabaseSpec) GetMaintenance() bool {
|
||||||
|
if m == nil || m.Maintenance == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return *m.Maintenance
|
||||||
|
}
|
|
@ -95,6 +95,8 @@ type DeploymentSpec struct {
|
||||||
|
|
||||||
ID *ServerIDGroupSpec `json:"id,omitempty"`
|
ID *ServerIDGroupSpec `json:"id,omitempty"`
|
||||||
|
|
||||||
|
Database *DatabaseSpec `json:"database,omitempty"`
|
||||||
|
|
||||||
Single ServerGroupSpec `json:"single"`
|
Single ServerGroupSpec `json:"single"`
|
||||||
Agents ServerGroupSpec `json:"agents"`
|
Agents ServerGroupSpec `json:"agents"`
|
||||||
DBServers ServerGroupSpec `json:"dbservers"`
|
DBServers ServerGroupSpec `json:"dbservers"`
|
||||||
|
@ -295,6 +297,9 @@ func (s *DeploymentSpec) SetDefaultsFrom(source DeploymentSpec) {
|
||||||
if s.AllowUnsafeUpgrade == nil {
|
if s.AllowUnsafeUpgrade == nil {
|
||||||
s.AllowUnsafeUpgrade = util.NewBoolOrNil(source.AllowUnsafeUpgrade)
|
s.AllowUnsafeUpgrade = util.NewBoolOrNil(source.AllowUnsafeUpgrade)
|
||||||
}
|
}
|
||||||
|
if s.Database == nil {
|
||||||
|
s.Database = source.Database.DeepCopy()
|
||||||
|
}
|
||||||
|
|
||||||
s.License.SetDefaultsFrom(source.License)
|
s.License.SetDefaultsFrom(source.License)
|
||||||
s.ExternalAccess.SetDefaultsFrom(source.ExternalAccess)
|
s.ExternalAccess.SetDefaultsFrom(source.ExternalAccess)
|
||||||
|
|
|
@ -119,6 +119,10 @@ const (
|
||||||
ActionTypeJWTPropagated ActionType = "JWTPropagated"
|
ActionTypeJWTPropagated ActionType = "JWTPropagated"
|
||||||
// ActionTypeClusterMemberCleanup removes member from cluster
|
// ActionTypeClusterMemberCleanup removes member from cluster
|
||||||
ActionTypeClusterMemberCleanup ActionType = "ClusterMemberCleanup"
|
ActionTypeClusterMemberCleanup ActionType = "ClusterMemberCleanup"
|
||||||
|
// ActionTypeEnableMaintenance enables maintenance on cluster.
|
||||||
|
ActionTypeEnableMaintenance ActionType = "EnableMaintenance"
|
||||||
|
// ActionTypeEnableMaintenance disables maintenance on cluster.
|
||||||
|
ActionTypeDisableMaintenance ActionType = "DisableMaintenance"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
26
pkg/apis/deployment/v1/zz_generated.deepcopy.go
generated
26
pkg/apis/deployment/v1/zz_generated.deepcopy.go
generated
|
@ -258,6 +258,27 @@ func (in ConditionList) DeepCopy() ConditionList {
|
||||||
return *out
|
return *out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *DatabaseSpec) DeepCopyInto(out *DatabaseSpec) {
|
||||||
|
*out = *in
|
||||||
|
if in.Maintenance != nil {
|
||||||
|
in, out := &in.Maintenance, &out.Maintenance
|
||||||
|
*out = new(bool)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatabaseSpec.
|
||||||
|
func (in *DatabaseSpec) DeepCopy() *DatabaseSpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(DatabaseSpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *DeploymentFeatures) DeepCopyInto(out *DeploymentFeatures) {
|
func (in *DeploymentFeatures) DeepCopyInto(out *DeploymentFeatures) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
@ -415,6 +436,11 @@ func (in *DeploymentSpec) DeepCopyInto(out *DeploymentSpec) {
|
||||||
*out = new(ServerIDGroupSpec)
|
*out = new(ServerIDGroupSpec)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
|
if in.Database != nil {
|
||||||
|
in, out := &in.Database, &out.Database
|
||||||
|
*out = new(DatabaseSpec)
|
||||||
|
(*in).DeepCopyInto(*out)
|
||||||
|
}
|
||||||
in.Single.DeepCopyInto(&out.Single)
|
in.Single.DeepCopyInto(&out.Single)
|
||||||
in.Agents.DeepCopyInto(&out.Agents)
|
in.Agents.DeepCopyInto(&out.Agents)
|
||||||
in.DBServers.DeepCopyInto(&out.DBServers)
|
in.DBServers.DeepCopyInto(&out.DBServers)
|
||||||
|
|
|
@ -22,41 +22,25 @@
|
||||||
|
|
||||||
package agency
|
package agency
|
||||||
|
|
||||||
type ArangoPlanDatabases map[string]ArangoPlanCollections
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
func (a ArangoPlanDatabases) IsDBServerInDatabases(name string) bool {
|
"github.com/arangodb/go-driver/agency"
|
||||||
for _, collections := range a {
|
"github.com/pkg/errors"
|
||||||
if collections.IsDBServerInCollections(name) {
|
)
|
||||||
return true
|
|
||||||
|
type Fetcher func(ctx context.Context, i interface{}, keyParts ...string) error
|
||||||
|
|
||||||
|
func NewFetcher(a agency.Agency) Fetcher {
|
||||||
|
return func(ctx context.Context, i interface{}, keyParts ...string) error {
|
||||||
|
if err := a.ReadKey(ctx, []string{
|
||||||
|
ArangoKey,
|
||||||
|
PlanKey,
|
||||||
|
PlanCollectionsKey,
|
||||||
|
}, i); err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ArangoPlanCollections map[string]ArangoPlanCollection
|
|
||||||
|
|
||||||
func (a ArangoPlanCollections) IsDBServerInCollections(name string) bool {
|
|
||||||
for _, collection := range a {
|
|
||||||
if collection.IsDBServerInShards(name) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type ArangoPlanCollection struct {
|
|
||||||
Shards ArangoPlanShard `json:"shards"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a ArangoPlanCollection) IsDBServerInShards(name string) bool {
|
|
||||||
for _, dbservers := range a.Shards {
|
|
||||||
for _, dbserver := range dbservers {
|
|
||||||
if dbserver == name {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type ArangoPlanShard map[string][]string
|
|
||||||
|
|
78
pkg/deployment/agency/database.go
Normal file
78
pkg/deployment/agency/database.go
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
//
|
||||||
|
// DISCLAIMER
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
// 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 agency
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetAgencyCollections(ctx context.Context, f Fetcher) (*ArangoPlanDatabases, error) {
|
||||||
|
ret := &ArangoPlanDatabases{}
|
||||||
|
|
||||||
|
if err := f(ctx, ret, ArangoKey, PlanKey, PlanCollectionsKey); err != nil {
|
||||||
|
return nil, errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ArangoPlanDatabases map[string]ArangoPlanCollections
|
||||||
|
|
||||||
|
func (a ArangoPlanDatabases) IsDBServerInDatabases(name string) bool {
|
||||||
|
for _, collections := range a {
|
||||||
|
if collections.IsDBServerInCollections(name) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type ArangoPlanCollections map[string]ArangoPlanCollection
|
||||||
|
|
||||||
|
func (a ArangoPlanCollections) IsDBServerInCollections(name string) bool {
|
||||||
|
for _, collection := range a {
|
||||||
|
if collection.IsDBServerInShards(name) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type ArangoPlanCollection struct {
|
||||||
|
Shards ArangoPlanShard `json:"shards"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a ArangoPlanCollection) IsDBServerInShards(name string) bool {
|
||||||
|
for _, dbservers := range a.Shards {
|
||||||
|
for _, dbserver := range dbservers {
|
||||||
|
if dbserver == name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type ArangoPlanShard map[string][]string
|
91
pkg/deployment/agency/maintenance.go
Normal file
91
pkg/deployment/agency/maintenance.go
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
//
|
||||||
|
// DISCLAIMER
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
// 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 agency
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/arangodb/go-driver"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Maintenance struct {
|
||||||
|
Result string `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Maintenance) Enabled() bool {
|
||||||
|
return m.Result == "Maintenance"
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMaintenanceMode(ctx context.Context, client driver.Client) (Maintenance, error) {
|
||||||
|
conn := client.Connection()
|
||||||
|
r, err := conn.NewRequest(http.MethodGet, "/_admin/cluster/maintenance")
|
||||||
|
if err != nil {
|
||||||
|
return Maintenance{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := conn.Do(ctx, r)
|
||||||
|
if err != nil {
|
||||||
|
return Maintenance{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := resp.CheckStatus(http.StatusOK); err != nil {
|
||||||
|
return Maintenance{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var m Maintenance
|
||||||
|
|
||||||
|
if err := resp.ParseBody("", &m); err != nil {
|
||||||
|
return Maintenance{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetMaintenanceMode(ctx context.Context, client driver.Client, enabled bool) error {
|
||||||
|
data := "on"
|
||||||
|
if !enabled {
|
||||||
|
data = "off"
|
||||||
|
}
|
||||||
|
|
||||||
|
conn := client.Connection()
|
||||||
|
r, err := conn.NewRequest(http.MethodPut, "/_admin/cluster/maintenance")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := r.SetBody(data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := conn.Do(ctx, r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := resp.CheckStatus(http.StatusOK); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -17,6 +17,8 @@
|
||||||
//
|
//
|
||||||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
//
|
//
|
||||||
|
// Author Adam Janikowski
|
||||||
|
//
|
||||||
|
|
||||||
package features
|
package features
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
//
|
//
|
||||||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
//
|
//
|
||||||
|
// Author Adam Janikowski
|
||||||
|
//
|
||||||
|
|
||||||
package features
|
package features
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
//
|
//
|
||||||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
//
|
//
|
||||||
|
// Author Adam Janikowski
|
||||||
|
//
|
||||||
|
|
||||||
package features
|
package features
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
//
|
//
|
||||||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
//
|
//
|
||||||
|
// Author Adam Janikowski
|
||||||
|
//
|
||||||
|
|
||||||
package features
|
package features
|
||||||
|
|
||||||
|
@ -70,7 +72,7 @@ func Init(cmd *cobra.Command) {
|
||||||
if v != "" && feature.EnterpriseRequired() {
|
if v != "" && feature.EnterpriseRequired() {
|
||||||
z = fmt.Sprintf("%s - Required version %s and Enterprise Edition", feature.Description(), v)
|
z = fmt.Sprintf("%s - Required version %s and Enterprise Edition", feature.Description(), v)
|
||||||
} else if v != "" {
|
} else if v != "" {
|
||||||
z = fmt.Sprintf("%s. Required version %s", feature.Description(), v)
|
z = fmt.Sprintf("%s - Required version %s", feature.Description(), v)
|
||||||
} else if feature.EnterpriseRequired() {
|
} else if feature.EnterpriseRequired() {
|
||||||
z = fmt.Sprintf("%s - Required Enterprise Edition", feature.Description())
|
z = fmt.Sprintf("%s - Required Enterprise Edition", feature.Description())
|
||||||
} else {
|
} else {
|
||||||
|
|
39
pkg/deployment/features/maintenance.go
Normal file
39
pkg/deployment/features/maintenance.go
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
//
|
||||||
|
// DISCLAIMER
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
// 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 features
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
registerFeature(maintenance)
|
||||||
|
}
|
||||||
|
|
||||||
|
var maintenance = &feature{
|
||||||
|
name: "maintenance",
|
||||||
|
description: "Database maintenance mode management",
|
||||||
|
version: "3.5.0",
|
||||||
|
enterpriseRequired: false,
|
||||||
|
enabledByDefault: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
func Maintenance() Feature {
|
||||||
|
return maintenance
|
||||||
|
}
|
|
@ -17,6 +17,8 @@
|
||||||
//
|
//
|
||||||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
//
|
//
|
||||||
|
// Author Adam Janikowski
|
||||||
|
//
|
||||||
|
|
||||||
package features
|
package features
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
//
|
//
|
||||||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
//
|
//
|
||||||
|
// Author Adam Janikowski
|
||||||
|
//
|
||||||
|
|
||||||
package reconcile
|
package reconcile
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
//
|
//
|
||||||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
//
|
//
|
||||||
|
// Author Adam Janikowski
|
||||||
|
//
|
||||||
|
|
||||||
package reconcile
|
package reconcile
|
||||||
|
|
||||||
|
|
72
pkg/deployment/reconcile/action_maintenance_disable.go
Normal file
72
pkg/deployment/reconcile/action_maintenance_disable.go
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
//
|
||||||
|
// DISCLAIMER
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
// 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 reconcile
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||||
|
"github.com/arangodb/kube-arangodb/pkg/deployment/agency"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
registerAction(api.ActionTypeDisableMaintenance, newDisableMaintenanceAction)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDisableMaintenanceAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
||||||
|
a := &actionDisableMaintenance{}
|
||||||
|
|
||||||
|
a.actionImpl = newActionImpl(log, action, actionCtx, addMemberTimeout, &a.newMemberID)
|
||||||
|
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
type actionDisableMaintenance struct {
|
||||||
|
// actionImpl implement timeout and member id functions
|
||||||
|
actionImpl
|
||||||
|
|
||||||
|
actionEmptyCheckProgress
|
||||||
|
|
||||||
|
newMemberID string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *actionDisableMaintenance) Start(ctx context.Context) (bool, error) {
|
||||||
|
switch a.actionCtx.GetMode() {
|
||||||
|
case api.DeploymentModeSingle:
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := a.actionCtx.GetDatabaseClient(ctx)
|
||||||
|
if err != nil {
|
||||||
|
a.log.Error().Err(err).Msgf("Unable to get agency client")
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := agency.SetMaintenanceMode(ctx, client, false); err != nil {
|
||||||
|
a.log.Error().Err(err).Msgf("Unable to disable maintenance")
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
72
pkg/deployment/reconcile/action_maintenance_enable.go
Normal file
72
pkg/deployment/reconcile/action_maintenance_enable.go
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
//
|
||||||
|
// DISCLAIMER
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
// 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 reconcile
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||||
|
"github.com/arangodb/kube-arangodb/pkg/deployment/agency"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
registerAction(api.ActionTypeEnableMaintenance, newEnableMaintenanceAction)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newEnableMaintenanceAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
||||||
|
a := &actionEnableMaintenance{}
|
||||||
|
|
||||||
|
a.actionImpl = newActionImpl(log, action, actionCtx, addMemberTimeout, &a.newMemberID)
|
||||||
|
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
type actionEnableMaintenance struct {
|
||||||
|
// actionImpl implement timeout and member id functions
|
||||||
|
actionImpl
|
||||||
|
|
||||||
|
actionEmptyCheckProgress
|
||||||
|
|
||||||
|
newMemberID string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *actionEnableMaintenance) Start(ctx context.Context) (bool, error) {
|
||||||
|
switch a.actionCtx.GetMode() {
|
||||||
|
case api.DeploymentModeSingle:
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := a.actionCtx.GetDatabaseClient(ctx)
|
||||||
|
if err != nil {
|
||||||
|
a.log.Error().Err(err).Msgf("Unable to get agency client")
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := agency.SetMaintenanceMode(ctx, client, true); err != nil {
|
||||||
|
a.log.Error().Err(err).Msgf("Unable to set maintenance")
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
44
pkg/deployment/reconcile/helper_maintenance.go
Normal file
44
pkg/deployment/reconcile/helper_maintenance.go
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
//
|
||||||
|
// DISCLAIMER
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
// 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 reconcile
|
||||||
|
|
||||||
|
import (
|
||||||
|
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||||
|
"github.com/arangodb/kube-arangodb/pkg/deployment/features"
|
||||||
|
)
|
||||||
|
|
||||||
|
func withMaintenance(plan ...api.Action) api.Plan {
|
||||||
|
if !features.Maintenance().Enabled() {
|
||||||
|
return plan
|
||||||
|
}
|
||||||
|
|
||||||
|
var newPlan api.Plan
|
||||||
|
|
||||||
|
newPlan = append(newPlan, api.NewAction(api.ActionTypeEnableMaintenance, api.ServerGroupUnknown, "", "Enable maintenance before actions"))
|
||||||
|
|
||||||
|
newPlan = append(newPlan, plan...)
|
||||||
|
|
||||||
|
newPlan = append(newPlan, api.NewAction(api.ActionTypeDisableMaintenance, api.ServerGroupUnknown, "", "Disable maintenance after actions"))
|
||||||
|
|
||||||
|
return newPlan
|
||||||
|
}
|
|
@ -97,13 +97,7 @@ func fetchAgency(ctx context.Context, log zerolog.Logger,
|
||||||
agencyCtx, agencyCancel := goContext.WithTimeout(ctx, time.Minute)
|
agencyCtx, agencyCancel := goContext.WithTimeout(ctx, time.Minute)
|
||||||
defer agencyCancel()
|
defer agencyCancel()
|
||||||
|
|
||||||
ret := &agency.ArangoPlanDatabases{}
|
return agency.GetAgencyCollections(agencyCtx, context.GetAgencyData)
|
||||||
|
|
||||||
if err := context.GetAgencyData(agencyCtx, cache, agency.ArangoKey, agency.PlanKey, agency.PlanCollectionsKey); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("not able to read from agency when agency is down")
|
return nil, fmt.Errorf("not able to read from agency when agency is down")
|
||||||
}
|
}
|
||||||
|
@ -214,6 +208,10 @@ func createPlan(ctx context.Context, log zerolog.Logger, apiObject k8sutil.APIOb
|
||||||
plan = pb.Apply(createJWTStatusUpdate)
|
plan = pb.Apply(createJWTStatusUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if plan.IsEmpty() {
|
||||||
|
plan = pb.Apply(createMaintenanceManagementPlan)
|
||||||
|
}
|
||||||
|
|
||||||
// Check for scale up/down
|
// Check for scale up/down
|
||||||
if plan.IsEmpty() {
|
if plan.IsEmpty() {
|
||||||
plan = pb.Apply(createScaleMemeberPlan)
|
plan = pb.Apply(createScaleMemeberPlan)
|
||||||
|
|
72
pkg/deployment/reconcile/plan_builder_common.go
Normal file
72
pkg/deployment/reconcile/plan_builder_common.go
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
//
|
||||||
|
// DISCLAIMER
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
// 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 reconcile
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||||
|
"github.com/arangodb/kube-arangodb/pkg/deployment/agency"
|
||||||
|
"github.com/arangodb/kube-arangodb/pkg/deployment/features"
|
||||||
|
"github.com/arangodb/kube-arangodb/pkg/deployment/resources/inspector"
|
||||||
|
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
)
|
||||||
|
|
||||||
|
func createMaintenanceManagementPlan(ctx context.Context,
|
||||||
|
log zerolog.Logger, apiObject k8sutil.APIObject,
|
||||||
|
spec api.DeploymentSpec, status api.DeploymentStatus,
|
||||||
|
cachedStatus inspector.Inspector, context PlanBuilderContext) api.Plan {
|
||||||
|
if spec.Mode.Get() == api.DeploymentModeSingle {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !features.Maintenance().Enabled() {
|
||||||
|
// Maintenance feature is not enabled
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := context.GetDatabaseClient(ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msgf("Unable to get agency client")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
m, err := agency.GetMaintenanceMode(ctx, client)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msgf("Unable to get agency maintenance mode")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !m.Enabled() && spec.Database.GetMaintenance() {
|
||||||
|
log.Info().Msgf("Enabling maintenance mode")
|
||||||
|
return api.Plan{api.NewAction(api.ActionTypeEnableMaintenance, api.ServerGroupUnknown, "")}
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.Enabled() && !spec.Database.GetMaintenance() {
|
||||||
|
log.Info().Msgf("Disabling maintenance mode")
|
||||||
|
return api.Plan{api.NewAction(api.ActionTypeEnableMaintenance, api.ServerGroupUnknown, "")}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -25,6 +25,8 @@ package reconcile
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/arangodb/go-driver/agency"
|
||||||
|
|
||||||
"github.com/arangodb/kube-arangodb/pkg/deployment/resources/inspector"
|
"github.com/arangodb/kube-arangodb/pkg/deployment/resources/inspector"
|
||||||
|
|
||||||
backupApi "github.com/arangodb/kube-arangodb/pkg/apis/backup/v1"
|
backupApi "github.com/arangodb/kube-arangodb/pkg/apis/backup/v1"
|
||||||
|
@ -69,6 +71,8 @@ type PlanBuilderContext interface {
|
||||||
GetBackup(backup string) (*backupApi.ArangoBackup, error)
|
GetBackup(backup string) (*backupApi.ArangoBackup, error)
|
||||||
// GetName receives deployment name
|
// GetName receives deployment name
|
||||||
GetName() string
|
GetName() string
|
||||||
|
// GetAgency returns a connection to the entire agency.
|
||||||
|
GetAgency(ctx context.Context) (agency.Agency, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// newPlanBuilderContext creates a PlanBuilderContext from the given context
|
// newPlanBuilderContext creates a PlanBuilderContext from the given context
|
||||||
|
|
|
@ -75,14 +75,25 @@ func createRestorePlan(ctx context.Context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return api.Plan{
|
return restorePlan(spec.Mode.Get())
|
||||||
api.NewAction(api.ActionTypeBackupRestore, api.ServerGroupUnknown, ""),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func restorePlan(mode api.DeploymentMode) api.Plan {
|
||||||
|
p := api.Plan{
|
||||||
|
api.NewAction(api.ActionTypeBackupRestore, api.ServerGroupUnknown, ""),
|
||||||
|
}
|
||||||
|
|
||||||
|
switch mode {
|
||||||
|
case api.DeploymentModeActiveFailover:
|
||||||
|
p = withMaintenance(p...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
func createRestorePlanEncryption(ctx context.Context, log zerolog.Logger, spec api.DeploymentSpec, status api.DeploymentStatus, builderCtx PlanBuilderContext, backup *backupv1.ArangoBackup) (bool, api.Plan) {
|
func createRestorePlanEncryption(ctx context.Context, log zerolog.Logger, spec api.DeploymentSpec, status api.DeploymentStatus, builderCtx PlanBuilderContext, backup *backupv1.ArangoBackup) (bool, api.Plan) {
|
||||||
if spec.RestoreEncryptionSecret != nil {
|
if spec.RestoreEncryptionSecret != nil {
|
||||||
if !spec.RocksDB.IsEncrypted() {
|
if !spec.RocksDB.IsEncrypted() {
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
//
|
//
|
||||||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
//
|
//
|
||||||
|
// Author Adam Janikowski
|
||||||
|
//
|
||||||
|
|
||||||
package resources
|
package resources
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
//
|
//
|
||||||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
//
|
//
|
||||||
|
// Author Adam Janikowski
|
||||||
|
//
|
||||||
|
|
||||||
package resources
|
package resources
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue