mirror of
https://github.com/arangodb/kube-arangodb.git
synced 2024-12-14 11:57:37 +00:00
[Feature] Early connections support (#1102)
This commit is contained in:
parent
a4e26f3ce4
commit
92afe451eb
14 changed files with 623 additions and 97 deletions
|
@ -2,6 +2,7 @@
|
|||
|
||||
## [master](https://github.com/arangodb/kube-arangodb/tree/master) (N/A)
|
||||
- (Feature) Add new field to DeploymentReplicationStatus with details on DC2DC sync status
|
||||
- (Feature) Early connections support
|
||||
|
||||
## [1.2.16](https://github.com/arangodb/kube-arangodb/tree/1.2.16) (2022-09-14)
|
||||
- (Feature) Add ArangoDeployment ServerGroupStatus
|
||||
|
|
|
@ -22,44 +22,80 @@ package cmd
|
|||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/arangodb/go-driver"
|
||||
"github.com/arangodb/go-driver/jwt"
|
||||
|
||||
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||
"github.com/arangodb/kube-arangodb/pkg/apis/shared"
|
||||
"github.com/arangodb/kube-arangodb/pkg/deployment/client"
|
||||
"github.com/arangodb/kube-arangodb/pkg/deployment/features"
|
||||
"github.com/arangodb/kube-arangodb/pkg/deployment/pod"
|
||||
"github.com/arangodb/kube-arangodb/pkg/deployment/resources"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/constants"
|
||||
)
|
||||
|
||||
var (
|
||||
cmdLifecycleProbe = &cobra.Command{
|
||||
Use: "probe",
|
||||
Run: cmdLifecycleProbeCheck,
|
||||
Run: cmdLifecycleProbeRun,
|
||||
}
|
||||
cmdLifecycleProbeLiveness = &cobra.Command{
|
||||
Use: "liveness",
|
||||
Run: cmdLifecycleProbeRun,
|
||||
}
|
||||
cmdLifecycleProbeReadiness = &cobra.Command{
|
||||
Use: "readiness",
|
||||
Run: cmdLifecycleProbeRun,
|
||||
}
|
||||
cmdLifecycleProbeStartUp = &cobra.Command{
|
||||
Use: "startup",
|
||||
Run: cmdLifecycleProbeRun,
|
||||
}
|
||||
|
||||
probeInput struct {
|
||||
SSL bool
|
||||
Auth bool
|
||||
Endpoint string
|
||||
JWTPath string
|
||||
Endpoint string
|
||||
JWTPath string
|
||||
ArangoDBVersion string
|
||||
ServerGroup string
|
||||
DeploymentMode string
|
||||
SSL bool
|
||||
Auth bool
|
||||
Enterprise bool
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
f := cmdLifecycleProbe.PersistentFlags()
|
||||
|
||||
cmdLifecycleProbe.AddCommand(cmdLifecycleProbeLiveness)
|
||||
cmdLifecycleProbe.AddCommand(cmdLifecycleProbeReadiness)
|
||||
cmdLifecycleProbe.AddCommand(cmdLifecycleProbeStartUp)
|
||||
|
||||
f.BoolVarP(&probeInput.SSL, "ssl", "", false, "Determines if SSL is enabled")
|
||||
f.BoolVarP(&probeInput.Auth, "auth", "", false, "Determines if authentication is enabled")
|
||||
f.StringVarP(&probeInput.Endpoint, "endpoint", "", "/_api/version", "Endpoint (path) to call for lifecycle probe")
|
||||
f.StringVarP(&probeInput.Endpoint, "endpoint", "", client.ServerApiVersionEndpoint, "Endpoint (path) to call for lifecycle probe")
|
||||
f.MarkDeprecated("endpoint", "Endpoint is chosen automatically by the lifecycle process")
|
||||
f.StringVarP(&probeInput.JWTPath, "jwt", "", shared.ClusterJWTSecretVolumeMountDir, "Path to the JWT tokens")
|
||||
f.StringVar(&probeInput.ArangoDBVersion, "arangodb-version", os.Getenv(resources.ArangoDBOverrideVersionEnv),
|
||||
"Version of the ArangoDB")
|
||||
f.StringVar(&probeInput.ServerGroup, "serverGroup", os.Getenv(resources.ArangoDBOverrideServerGroupEnv),
|
||||
"Name of the group where a server belongs to")
|
||||
f.StringVar(&probeInput.DeploymentMode, "deploymentMode", os.Getenv(resources.ArangoDBOverrideDeploymentModeEnv),
|
||||
"A deployment mode (Cluster, Single, ActiveFailover)")
|
||||
enterprise, _ := strconv.ParseBool(os.Getenv(resources.ArangoDBOverrideEnterpriseEnv))
|
||||
f.BoolVar(&probeInput.Enterprise, "enterprise", enterprise, "Determines if ArangoDB is enterprise")
|
||||
}
|
||||
|
||||
func probeClient() *http.Client {
|
||||
|
@ -147,10 +183,10 @@ func addAuthHeader(req *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func doRequest() (*http.Response, error) {
|
||||
func doRequest(endpoint string) (*http.Response, error) {
|
||||
client := probeClient()
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, probeEndpoint(probeInput.Endpoint), nil)
|
||||
req, err := http.NewRequest(http.MethodGet, probeEndpoint(endpoint), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -162,22 +198,25 @@ func doRequest() (*http.Response, error) {
|
|||
return client.Do(req)
|
||||
}
|
||||
|
||||
func cmdLifecycleProbeCheck(cmd *cobra.Command, args []string) {
|
||||
if err := cmdLifecycleProbeCheckE(); err != nil {
|
||||
func cmdLifecycleProbeRun(cmd *cobra.Command, _ []string) {
|
||||
if err := cmdLifecycleProbeRunE(cmd); err != nil {
|
||||
log.Error().Err(err).Msgf("Fatal")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func cmdLifecycleProbeCheckE() error {
|
||||
resp, err := doRequest()
|
||||
func cmdLifecycleProbeRunE(cmd *cobra.Command) error {
|
||||
endpoint := getEndpoint(api.ProbeType(cmd.Use))
|
||||
resp, err := doRequest(endpoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.Body != nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
if resp.Body != nil {
|
||||
defer resp.Body.Close()
|
||||
if data, err := ioutil.ReadAll(resp.Body); err == nil {
|
||||
return errors.Errorf("Unexpected code: %d - %s", resp.StatusCode, string(data))
|
||||
}
|
||||
|
@ -186,7 +225,51 @@ func cmdLifecycleProbeCheckE() error {
|
|||
return errors.Errorf("Unexpected code: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
if endpoint == client.ServerStatusEndpoint {
|
||||
// When server status endpoint is used then HTTP status code 200 is not enough.
|
||||
// The progress should be also checked.
|
||||
if resp.Body == nil {
|
||||
return errors.Errorf("Expected body from the \"%s\" endpoint", endpoint)
|
||||
}
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return errors.Errorf("Failed to read body from the \"%s\" endpoint", endpoint)
|
||||
}
|
||||
|
||||
status := client.ServerStatus{}
|
||||
if err = json.Unmarshal(data, &status); err != nil {
|
||||
return errors.Errorf("Failed to unmarshal %s into server status", string(data))
|
||||
}
|
||||
|
||||
if progress, ok := status.GetProgress(); !ok {
|
||||
return errors.Errorf("server not ready: %s", progress)
|
||||
}
|
||||
}
|
||||
|
||||
log.Info().Msgf("Check passed")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getEndpoint returns endpoint to the ArangoDB instance where readiness should be checked.
|
||||
func getEndpoint(probeType api.ProbeType) string {
|
||||
if probeType == api.ProbeTypeReadiness {
|
||||
if probeInput.DeploymentMode == string(api.DeploymentModeActiveFailover) {
|
||||
v := driver.Version(probeInput.ArangoDBVersion)
|
||||
if features.FailoverLeadership().Supported(v, probeInput.Enterprise) {
|
||||
return client.ServerApiVersionEndpoint
|
||||
}
|
||||
}
|
||||
|
||||
return client.ServerAvailabilityEndpoint
|
||||
}
|
||||
|
||||
if probeInput.ServerGroup == api.ServerGroupDBServersString {
|
||||
v := driver.Version(probeInput.ArangoDBVersion)
|
||||
if features.Version310().Supported(v, probeInput.Enterprise) {
|
||||
return client.ServerStatusEndpoint
|
||||
}
|
||||
}
|
||||
|
||||
return client.ServerApiVersionEndpoint
|
||||
}
|
||||
|
|
29
pkg/apis/deployment/v1/probes.go
Normal file
29
pkg/apis/deployment/v1/probes.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2016-2022 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 v1
|
||||
|
||||
type ProbeType string
|
||||
|
||||
const (
|
||||
ProbeTypeLiveness = "liveness"
|
||||
ProbeTypeReadiness = "readiness"
|
||||
ProbeTypeStartUp = "startup"
|
||||
)
|
29
pkg/apis/deployment/v2alpha1/probes.go
Normal file
29
pkg/apis/deployment/v2alpha1/probes.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2016-2022 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 v2alpha1
|
||||
|
||||
type ProbeType string
|
||||
|
||||
const (
|
||||
ProbeTypeLiveness = "liveness"
|
||||
ProbeTypeReadiness = "readiness"
|
||||
ProbeTypeStartUp = "startup"
|
||||
)
|
76
pkg/deployment/client/status.go
Normal file
76
pkg/deployment/client/status.go
Normal file
|
@ -0,0 +1,76 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2016-2022 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 client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// ServerProgressPhaseInWait describes success progress state of a server.
|
||||
ServerProgressPhaseInWait = "in wait"
|
||||
// ServerStatusEndpoint describes endpoint of a server status.
|
||||
ServerStatusEndpoint = "/_admin/status"
|
||||
// ServerApiVersionEndpoint describes endpoint of a server version.
|
||||
ServerApiVersionEndpoint = "/_api/version"
|
||||
// ServerAvailabilityEndpoint describes endpoint of a server availability.
|
||||
ServerAvailabilityEndpoint = "/_admin/server/availability"
|
||||
)
|
||||
|
||||
// ServerProgress describes server progress.
|
||||
type ServerProgress struct {
|
||||
// Phase is a name of the lifecycle phase the instance is currently in.
|
||||
Phase string `json:"phase,omitempty"`
|
||||
// Feature is internal name of the feature that is currently being prepared
|
||||
Feature string `json:"feature,omitempty"`
|
||||
// Current recovery sequence number value, if the instance is currently recovering.
|
||||
// If the instance is already past the recovery, this attribute contains the last handled recovery sequence number.
|
||||
RecoveryTick int `json:"recoveryTick,omitempty"`
|
||||
}
|
||||
|
||||
// ServerInfo describes server information.
|
||||
type ServerInfo struct {
|
||||
ServerProgress ServerProgress `json:"progress,omitempty"`
|
||||
}
|
||||
|
||||
// ServerStatus describes server status.
|
||||
type ServerStatus struct {
|
||||
ServerInfo ServerInfo `json:"serverInfo,omitempty"`
|
||||
}
|
||||
|
||||
// GetProgress returns human-readable progress status of the server, and true if server is ready.
|
||||
func (s ServerStatus) GetProgress() (string, bool) {
|
||||
p := s.ServerInfo.ServerProgress
|
||||
var result strings.Builder
|
||||
|
||||
if len(p.Feature) > 0 {
|
||||
result.WriteString("feature: " + p.Feature + ", ")
|
||||
}
|
||||
|
||||
result.WriteString("phase: " + p.Phase)
|
||||
|
||||
if p.RecoveryTick > 0 {
|
||||
result.WriteString(", recoveryTick: " + fmt.Sprintf("%d", p.RecoveryTick))
|
||||
}
|
||||
|
||||
return result.String(), p.Phase == ServerProgressPhaseInWait
|
||||
}
|
|
@ -52,7 +52,7 @@ func TestEnsurePod_ArangoDB_Encryption(t *testing.T) {
|
|||
firstAgentStatus,
|
||||
},
|
||||
},
|
||||
Images: createTestImagesWithVersion(false, "3.7.0"),
|
||||
Images: createTestImagesWithVersion(false, testVersion),
|
||||
}
|
||||
|
||||
testCase.createTestPodData(deployment, api.ServerGroupAgents, firstAgentStatus)
|
||||
|
@ -117,7 +117,7 @@ func TestEnsurePod_ArangoDB_Encryption(t *testing.T) {
|
|||
firstDBServerStatus,
|
||||
},
|
||||
},
|
||||
Images: createTestImagesWithVersion(false, "3.7.0"),
|
||||
Images: createTestImagesWithVersion(false, testVersion),
|
||||
}
|
||||
|
||||
testCase.createTestPodData(deployment, api.ServerGroupDBServers, firstDBServerStatus)
|
||||
|
@ -200,7 +200,7 @@ func TestEnsurePod_ArangoDB_Encryption(t *testing.T) {
|
|||
firstAgentStatus,
|
||||
},
|
||||
},
|
||||
Images: createTestImagesWithVersion(true, "3.7.0"),
|
||||
Images: createTestImagesWithVersion(true, testVersion),
|
||||
}
|
||||
|
||||
testCase.createTestPodData(deployment, api.ServerGroupAgents, firstAgentStatus)
|
||||
|
@ -263,7 +263,7 @@ func TestEnsurePod_ArangoDB_Encryption(t *testing.T) {
|
|||
firstAgentStatus,
|
||||
},
|
||||
},
|
||||
Images: createTestImagesWithVersion(true, "3.7.0"),
|
||||
Images: createTestImagesWithVersion(true, testVersion),
|
||||
}
|
||||
|
||||
testCase.createTestPodData(deployment, api.ServerGroupAgents, firstAgentStatus)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
package deployment
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
core "k8s.io/api/core/v1"
|
||||
|
@ -32,6 +33,13 @@ import (
|
|||
)
|
||||
|
||||
func TestEnsurePod_ArangoDB_Probe(t *testing.T) {
|
||||
addEarlyConnection := func() k8sutil.OptionPairs {
|
||||
args := k8sutil.NewOptionPair()
|
||||
args.Add("--server.early-connections", true)
|
||||
|
||||
return args
|
||||
}
|
||||
|
||||
testCases := []testCaseStruct{
|
||||
{
|
||||
Name: "Agent Pod default probes",
|
||||
|
@ -413,6 +421,278 @@ func TestEnsurePod_ArangoDB_Probe(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "DBServer with early connections",
|
||||
ArangoDeployment: &api.ArangoDeployment{
|
||||
Spec: api.DeploymentSpec{
|
||||
Image: util.NewString(createTestImageForVersion("3.10.0")),
|
||||
Authentication: noAuthentication,
|
||||
TLS: noTLS,
|
||||
},
|
||||
},
|
||||
Helper: func(t *testing.T, deployment *Deployment, testCase *testCaseStruct) {
|
||||
deployment.currentObjectStatus = &api.DeploymentStatus{
|
||||
Members: api.DeploymentStatusMembers{
|
||||
DBServers: api.MemberStatusList{
|
||||
firstDBServerStatus,
|
||||
},
|
||||
},
|
||||
Images: createTestImagesWithVersion(true, "3.10.0"),
|
||||
}
|
||||
|
||||
testCase.createTestPodData(deployment, api.ServerGroupDBServers, firstDBServerStatus)
|
||||
testCase.ExpectedPod.Spec.Containers[0].StartupProbe = createTestStartupProbe(cmdProbe, false, "",
|
||||
math.MaxInt32)
|
||||
testCase.ExpectedPod.Spec.Containers[0].LivenessProbe.FailureThreshold = math.MaxInt32
|
||||
},
|
||||
Features: testCaseFeatures{
|
||||
Version310: true,
|
||||
},
|
||||
ExpectedEvent: "member dbserver is created",
|
||||
ExpectedPod: core.Pod{
|
||||
Spec: core.PodSpec{
|
||||
Volumes: []core.Volume{
|
||||
k8sutil.CreateVolumeEmptyDir(shared.ArangodVolumeName),
|
||||
},
|
||||
Containers: []core.Container{
|
||||
{
|
||||
Name: shared.ServerContainerName,
|
||||
Image: createTestImageForVersion("3.10.0"),
|
||||
Command: createTestCommandForDBServer(firstDBServerStatus.ID, false, false, false, addEarlyConnection),
|
||||
Ports: createTestPorts(),
|
||||
VolumeMounts: []core.VolumeMount{
|
||||
k8sutil.ArangodVolumeMount(),
|
||||
},
|
||||
Resources: emptyResources,
|
||||
LivenessProbe: createTestLivenessProbe(cmdProbe, false, "", shared.ArangoPort),
|
||||
ImagePullPolicy: core.PullIfNotPresent,
|
||||
SecurityContext: securityContext.NewSecurityContext(),
|
||||
},
|
||||
},
|
||||
RestartPolicy: core.RestartPolicyNever,
|
||||
TerminationGracePeriodSeconds: &defaultDBServerTerminationTimeout,
|
||||
Hostname: testDeploymentName + "-" + api.ServerGroupDBServersString + "-" + firstDBServerStatus.ID,
|
||||
Subdomain: testDeploymentName + "-int",
|
||||
Affinity: k8sutil.CreateAffinity(testDeploymentName, api.ServerGroupDBServersString,
|
||||
false, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "DBServer without early connections because version is lower than 3.10.0",
|
||||
ArangoDeployment: &api.ArangoDeployment{
|
||||
Spec: api.DeploymentSpec{
|
||||
Image: util.NewString(createTestImageForVersion("3.9.2")),
|
||||
Authentication: noAuthentication,
|
||||
TLS: noTLS,
|
||||
},
|
||||
},
|
||||
Helper: func(t *testing.T, deployment *Deployment, testCase *testCaseStruct) {
|
||||
deployment.currentObjectStatus = &api.DeploymentStatus{
|
||||
Members: api.DeploymentStatusMembers{
|
||||
DBServers: api.MemberStatusList{
|
||||
firstDBServerStatus,
|
||||
},
|
||||
},
|
||||
Images: createTestImagesWithVersion(false, "3.9.2"),
|
||||
}
|
||||
|
||||
testCase.createTestPodData(deployment, api.ServerGroupDBServers, firstDBServerStatus)
|
||||
},
|
||||
Features: testCaseFeatures{
|
||||
Version310: true,
|
||||
},
|
||||
ExpectedEvent: "member dbserver is created",
|
||||
ExpectedPod: core.Pod{
|
||||
Spec: core.PodSpec{
|
||||
Volumes: []core.Volume{
|
||||
k8sutil.CreateVolumeEmptyDir(shared.ArangodVolumeName),
|
||||
},
|
||||
Containers: []core.Container{
|
||||
{
|
||||
Name: shared.ServerContainerName,
|
||||
Image: createTestImageForVersion("3.9.2"),
|
||||
Command: createTestCommandForDBServer(firstDBServerStatus.ID, false, false, false),
|
||||
Ports: createTestPorts(),
|
||||
VolumeMounts: []core.VolumeMount{
|
||||
k8sutil.ArangodVolumeMount(),
|
||||
},
|
||||
Resources: emptyResources,
|
||||
LivenessProbe: createTestLivenessProbe(httpProbe, false, "", shared.ArangoPort),
|
||||
ImagePullPolicy: core.PullIfNotPresent,
|
||||
SecurityContext: securityContext.NewSecurityContext(),
|
||||
},
|
||||
},
|
||||
RestartPolicy: core.RestartPolicyNever,
|
||||
TerminationGracePeriodSeconds: &defaultDBServerTerminationTimeout,
|
||||
Hostname: testDeploymentName + "-" + api.ServerGroupDBServersString + "-" + firstDBServerStatus.ID,
|
||||
Subdomain: testDeploymentName + "-int",
|
||||
Affinity: k8sutil.CreateAffinity(testDeploymentName, api.ServerGroupDBServersString,
|
||||
false, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "DBServer without early connections because 3.10 feature is disabled",
|
||||
ArangoDeployment: &api.ArangoDeployment{
|
||||
Spec: api.DeploymentSpec{
|
||||
Image: util.NewString(createTestImageForVersion("3.10.0")),
|
||||
Authentication: noAuthentication,
|
||||
TLS: noTLS,
|
||||
},
|
||||
},
|
||||
Helper: func(t *testing.T, deployment *Deployment, testCase *testCaseStruct) {
|
||||
deployment.currentObjectStatus = &api.DeploymentStatus{
|
||||
Members: api.DeploymentStatusMembers{
|
||||
DBServers: api.MemberStatusList{
|
||||
firstDBServerStatus,
|
||||
},
|
||||
},
|
||||
Images: createTestImagesWithVersion(false, "3.10.0"),
|
||||
}
|
||||
|
||||
testCase.createTestPodData(deployment, api.ServerGroupDBServers, firstDBServerStatus)
|
||||
},
|
||||
Features: testCaseFeatures{
|
||||
Version310: false,
|
||||
},
|
||||
ExpectedEvent: "member dbserver is created",
|
||||
ExpectedPod: core.Pod{
|
||||
Spec: core.PodSpec{
|
||||
Volumes: []core.Volume{
|
||||
k8sutil.CreateVolumeEmptyDir(shared.ArangodVolumeName),
|
||||
},
|
||||
Containers: []core.Container{
|
||||
{
|
||||
Name: shared.ServerContainerName,
|
||||
Image: createTestImageForVersion("3.10.0"),
|
||||
Command: createTestCommandForDBServer(firstDBServerStatus.ID, false, false, false),
|
||||
Ports: createTestPorts(),
|
||||
VolumeMounts: []core.VolumeMount{
|
||||
k8sutil.ArangodVolumeMount(),
|
||||
},
|
||||
Resources: emptyResources,
|
||||
LivenessProbe: createTestLivenessProbe(httpProbe, false, "", shared.ArangoPort),
|
||||
ImagePullPolicy: core.PullIfNotPresent,
|
||||
SecurityContext: securityContext.NewSecurityContext(),
|
||||
},
|
||||
},
|
||||
RestartPolicy: core.RestartPolicyNever,
|
||||
TerminationGracePeriodSeconds: &defaultDBServerTerminationTimeout,
|
||||
Hostname: testDeploymentName + "-" + api.ServerGroupDBServersString + "-" + firstDBServerStatus.ID,
|
||||
Subdomain: testDeploymentName + "-int",
|
||||
Affinity: k8sutil.CreateAffinity(testDeploymentName, api.ServerGroupDBServersString,
|
||||
false, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Coordinator should be without early connections",
|
||||
ArangoDeployment: &api.ArangoDeployment{
|
||||
Spec: api.DeploymentSpec{
|
||||
Image: util.NewString(createTestImageForVersion("3.10.0")),
|
||||
Authentication: noAuthentication,
|
||||
TLS: noTLS,
|
||||
},
|
||||
},
|
||||
Helper: func(t *testing.T, deployment *Deployment, testCase *testCaseStruct) {
|
||||
deployment.currentObjectStatus = &api.DeploymentStatus{
|
||||
Members: api.DeploymentStatusMembers{
|
||||
Coordinators: api.MemberStatusList{
|
||||
firstCoordinatorStatus,
|
||||
},
|
||||
},
|
||||
Images: createTestImagesWithVersion(false, "3.10.0"),
|
||||
}
|
||||
|
||||
testCase.createTestPodData(deployment, api.ServerGroupCoordinators, firstCoordinatorStatus)
|
||||
},
|
||||
Features: testCaseFeatures{
|
||||
Version310: true,
|
||||
},
|
||||
ExpectedEvent: "member coordinator is created",
|
||||
ExpectedPod: core.Pod{
|
||||
Spec: core.PodSpec{
|
||||
Volumes: []core.Volume{
|
||||
k8sutil.CreateVolumeEmptyDir(shared.ArangodVolumeName),
|
||||
},
|
||||
Containers: []core.Container{
|
||||
{
|
||||
Name: shared.ServerContainerName,
|
||||
Image: createTestImageForVersion("3.10.0"),
|
||||
Command: createTestCommandForCoordinator(firstCoordinatorStatus.ID, false, false),
|
||||
Ports: createTestPorts(),
|
||||
VolumeMounts: []core.VolumeMount{
|
||||
k8sutil.ArangodVolumeMount(),
|
||||
},
|
||||
Resources: emptyResources,
|
||||
ReadinessProbe: createTestReadinessProbe(httpProbe, false, ""),
|
||||
ImagePullPolicy: core.PullIfNotPresent,
|
||||
SecurityContext: securityContext.NewSecurityContext(),
|
||||
},
|
||||
},
|
||||
RestartPolicy: core.RestartPolicyNever,
|
||||
TerminationGracePeriodSeconds: &defaultCoordinatorTerminationTimeout,
|
||||
Hostname: testDeploymentName + "-" + api.ServerGroupCoordinatorsString + "-" + firstCoordinatorStatus.ID,
|
||||
Subdomain: testDeploymentName + "-int",
|
||||
Affinity: k8sutil.CreateAffinity(testDeploymentName, api.ServerGroupCoordinatorsString,
|
||||
false, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Agent should be without early connections",
|
||||
ArangoDeployment: &api.ArangoDeployment{
|
||||
Spec: api.DeploymentSpec{
|
||||
Image: util.NewString(createTestImageForVersion("3.10.0")),
|
||||
Authentication: noAuthentication,
|
||||
TLS: noTLS,
|
||||
},
|
||||
},
|
||||
Helper: func(t *testing.T, deployment *Deployment, testCase *testCaseStruct) {
|
||||
deployment.currentObjectStatus = &api.DeploymentStatus{
|
||||
Members: api.DeploymentStatusMembers{
|
||||
Agents: api.MemberStatusList{
|
||||
firstAgentStatus,
|
||||
},
|
||||
},
|
||||
Images: createTestImagesWithVersion(false, "3.10.0"),
|
||||
}
|
||||
testCase.createTestPodData(deployment, api.ServerGroupAgents, firstAgentStatus)
|
||||
},
|
||||
Features: testCaseFeatures{
|
||||
Version310: true,
|
||||
},
|
||||
ExpectedEvent: "member agent is created",
|
||||
ExpectedPod: core.Pod{
|
||||
Spec: core.PodSpec{
|
||||
Volumes: []core.Volume{
|
||||
k8sutil.CreateVolumeEmptyDir(shared.ArangodVolumeName),
|
||||
},
|
||||
Containers: []core.Container{
|
||||
{
|
||||
Name: shared.ServerContainerName,
|
||||
Image: createTestImageForVersion("3.10.0"),
|
||||
Command: createTestCommandForAgent(firstAgentStatus.ID, false, false, false),
|
||||
Ports: createTestPorts(),
|
||||
VolumeMounts: []core.VolumeMount{
|
||||
k8sutil.ArangodVolumeMount(),
|
||||
},
|
||||
Resources: emptyResources,
|
||||
LivenessProbe: createTestLivenessProbe(httpProbe, false, "", shared.ArangoPort),
|
||||
ImagePullPolicy: core.PullIfNotPresent,
|
||||
SecurityContext: securityContext.NewSecurityContext(),
|
||||
},
|
||||
},
|
||||
RestartPolicy: core.RestartPolicyNever,
|
||||
TerminationGracePeriodSeconds: &defaultAgentTerminationTimeout,
|
||||
Hostname: testDeploymentName + "-" + api.ServerGroupAgentsString + "-" + firstAgentStatus.ID,
|
||||
Subdomain: testDeploymentName + "-int",
|
||||
Affinity: k8sutil.CreateAffinity(testDeploymentName, api.ServerGroupAgentsString,
|
||||
false, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
runTestCases(t, testCases...)
|
||||
|
|
|
@ -134,7 +134,7 @@ func TestEnsurePod_ArangoDB_TLS_SNI(t *testing.T) {
|
|||
Name: "Pod SNI Mounts - Enterprise - 3.6.0",
|
||||
ArangoDeployment: &api.ArangoDeployment{
|
||||
Spec: api.DeploymentSpec{
|
||||
Image: util.NewString(testImage),
|
||||
Image: util.NewString(createTestImageForVersion("3.6.0")),
|
||||
Authentication: noAuthentication,
|
||||
TLS: func() api.TLSSpec {
|
||||
s := tlsSpec.DeepCopy()
|
||||
|
@ -183,7 +183,7 @@ func TestEnsurePod_ArangoDB_TLS_SNI(t *testing.T) {
|
|||
Containers: []core.Container{
|
||||
{
|
||||
Name: shared.ServerContainerName,
|
||||
Image: testImage,
|
||||
Image: createTestImageForVersion("3.6.0"),
|
||||
Command: createTestCommandForCoordinator(firstCoordinatorStatus.ID, true, false),
|
||||
Ports: createTestPorts(),
|
||||
VolumeMounts: []core.VolumeMount{
|
||||
|
@ -244,7 +244,7 @@ func TestEnsurePod_ArangoDB_TLS_SNI(t *testing.T) {
|
|||
firstCoordinatorStatus,
|
||||
},
|
||||
},
|
||||
Images: createTestImagesWithVersion(false, "3.7.0"),
|
||||
Images: createTestImagesWithVersion(false, testVersion),
|
||||
}
|
||||
testCase.createTestPodData(deployment, api.ServerGroupCoordinators, firstCoordinatorStatus)
|
||||
},
|
||||
|
@ -319,7 +319,7 @@ func TestEnsurePod_ArangoDB_TLS_SNI(t *testing.T) {
|
|||
firstCoordinatorStatus,
|
||||
},
|
||||
},
|
||||
Images: createTestImagesWithVersion(true, "3.7.0"),
|
||||
Images: createTestImagesWithVersion(true, testVersion),
|
||||
}
|
||||
testCase.createTestPodData(deployment, api.ServerGroupCoordinators, firstCoordinatorStatus)
|
||||
},
|
||||
|
@ -427,7 +427,7 @@ func TestEnsurePod_ArangoDB_TLS_SNI(t *testing.T) {
|
|||
firstDBServerStatus,
|
||||
},
|
||||
},
|
||||
Images: createTestImagesWithVersion(true, "3.7.0"),
|
||||
Images: createTestImagesWithVersion(true, testVersion),
|
||||
}
|
||||
testCase.createTestPodData(deployment, api.ServerGroupDBServers, firstDBServerStatus)
|
||||
},
|
||||
|
|
|
@ -112,6 +112,7 @@ func runTestCase(t *testing.T, testCase testCaseStruct) {
|
|||
// Set features
|
||||
{
|
||||
*features.EncryptionRotation().EnabledPointer() = testCase.Features.EncryptionRotation
|
||||
*features.Version310().EnabledPointer() = testCase.Features.Version310
|
||||
require.Equal(t, testCase.Features.EncryptionRotation, *features.EncryptionRotation().EnabledPointer())
|
||||
*features.JWTRotation().EnabledPointer() = testCase.Features.JWTRotation
|
||||
*features.TLSSNI().EnabledPointer() = testCase.Features.TLSSNI
|
||||
|
|
|
@ -22,7 +22,6 @@ package deployment
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
@ -62,7 +61,8 @@ const (
|
|||
testNamespace = "default"
|
||||
testDeploymentName = "test"
|
||||
testVersion = "3.7.0"
|
||||
testImage = "arangodb/arangodb:" + testVersion
|
||||
testImagePrefix = "arangodb/arangodb:"
|
||||
testImage = testImagePrefix + testVersion
|
||||
testCASecretName = "testCA"
|
||||
testJWTSecretName = "testJWT"
|
||||
testExporterToken = "testExporterToken"
|
||||
|
@ -72,13 +72,13 @@ const (
|
|||
testServiceAccountName = "testServiceAccountName"
|
||||
testPriorityClassName = "testPriority"
|
||||
testImageOperator = "arangodb/kube-arangodb:0.3.16"
|
||||
|
||||
testYes = "yes"
|
||||
testProbeDBServerRetires = 4320 // 6 hours divide by 5.
|
||||
testYes = "yes"
|
||||
)
|
||||
|
||||
type testCaseFeatures struct {
|
||||
TLSSNI, TLSRotation, JWTRotation, EncryptionRotation bool
|
||||
Graceful *bool
|
||||
TLSSNI, TLSRotation, JWTRotation, EncryptionRotation, Version310 bool
|
||||
Graceful *bool
|
||||
}
|
||||
|
||||
type testCaseStruct struct {
|
||||
|
@ -95,6 +95,10 @@ type testCaseStruct struct {
|
|||
DropInit bool
|
||||
}
|
||||
|
||||
func createTestImageForVersion(version string) string {
|
||||
return testImagePrefix + version
|
||||
}
|
||||
|
||||
func createTestTLSVolume(serverGroupString, ID string) core.Volume {
|
||||
return k8sutil.CreateVolumeWithSecret(shared.TlsKeyfileVolumeName,
|
||||
k8sutil.CreateTLSKeyfileSecretName(testDeploymentName, serverGroupString, ID))
|
||||
|
@ -138,11 +142,12 @@ func createTestReadinessSimpleProbe(mode string, secure bool, authorization stri
|
|||
}
|
||||
|
||||
func createTestLivenessProbe(mode string, secure bool, authorization string, port int) *core.Probe {
|
||||
return getProbeCreator(mode)(secure, authorization, "/_api/version", port).Create()
|
||||
return getProbeCreator(mode)(secure, authorization, "/_api/version", port, api.ProbeTypeLiveness).Create()
|
||||
}
|
||||
|
||||
func createTestReadinessProbe(mode string, secure bool, authorization string) *core.Probe {
|
||||
p := getProbeCreator(mode)(secure, authorization, "/_admin/server/availability", shared.ArangoPort).Create()
|
||||
p := getProbeCreator(mode)(secure, authorization, "/_admin/server/availability", shared.ArangoPort,
|
||||
api.ProbeTypeReadiness).Create()
|
||||
|
||||
p.InitialDelaySeconds = 2
|
||||
p.PeriodSeconds = 2
|
||||
|
@ -151,7 +156,7 @@ func createTestReadinessProbe(mode string, secure bool, authorization string) *c
|
|||
}
|
||||
|
||||
func createTestStartupProbe(mode string, secure bool, authorization string, failureThreshold int32) *core.Probe {
|
||||
p := getProbeCreator(mode)(secure, authorization, "/_api/version", shared.ArangoPort).Create()
|
||||
p := getProbeCreator(mode)(secure, authorization, "/_api/version", shared.ArangoPort, api.ProbeTypeStartUp).Create()
|
||||
|
||||
p.InitialDelaySeconds = 1
|
||||
p.PeriodSeconds = 5
|
||||
|
@ -160,7 +165,7 @@ func createTestStartupProbe(mode string, secure bool, authorization string, fail
|
|||
return p
|
||||
}
|
||||
|
||||
type probeCreator func(secure bool, authorization, endpoint string, port int) resources.Probe
|
||||
type probeCreator func(secure bool, authorization, endpoint string, port int, probe api.ProbeType) resources.Probe
|
||||
|
||||
const (
|
||||
cmdProbe = "cmdProbe"
|
||||
|
@ -177,24 +182,24 @@ func getProbeCreator(t string) probeCreator {
|
|||
}
|
||||
|
||||
func getHTTPProbeCreator() probeCreator {
|
||||
return func(secure bool, authorization, endpoint string, port int) resources.Probe {
|
||||
return func(secure bool, authorization, endpoint string, port int, _ api.ProbeType) resources.Probe {
|
||||
return createHTTPTestProbe(secure, authorization, endpoint, port)
|
||||
}
|
||||
}
|
||||
|
||||
func getCMDProbeCreator() probeCreator {
|
||||
return func(secure bool, authorization, endpoint string, port int) resources.Probe {
|
||||
return createCMDTestProbe(secure, authorization != "", endpoint)
|
||||
return func(secure bool, authorization, endpoint string, port int, probeType api.ProbeType) resources.Probe {
|
||||
return createCMDTestProbe(secure, authorization != "", probeType)
|
||||
}
|
||||
}
|
||||
|
||||
func createCMDTestProbe(secure, authorization bool, endpoint string) resources.Probe {
|
||||
func createCMDTestProbe(secure, authorization bool, probeType api.ProbeType) resources.Probe {
|
||||
bin, _ := os.Executable()
|
||||
args := []string{
|
||||
filepath.Join(k8sutil.LifecycleVolumeMountDir, filepath.Base(bin)),
|
||||
"lifecycle",
|
||||
"probe",
|
||||
fmt.Sprintf("--endpoint=%s", endpoint),
|
||||
string(probeType),
|
||||
}
|
||||
|
||||
if secure {
|
||||
|
@ -270,7 +275,8 @@ func createTestCommandForDBServer(name string, tls, auth, encryptionRocksDB bool
|
|||
args.Merge(mod())
|
||||
}
|
||||
|
||||
return append(command, args.Unique().AsArgs()...)
|
||||
sorted := args.Sort().Unique().AsArgs()
|
||||
return append(command, sorted...)
|
||||
}
|
||||
|
||||
func createTestCommandForCoordinator(name string, tls, auth bool, mods ...func() k8sutil.OptionPairs) []string {
|
||||
|
@ -526,11 +532,12 @@ func createTestPorts() []core.ContainerPort {
|
|||
}
|
||||
|
||||
func createTestImagesWithVersion(enterprise bool, version driver.Version) api.ImageInfoList {
|
||||
i := createTestImageForVersion(string(version))
|
||||
return api.ImageInfoList{
|
||||
{
|
||||
Image: testImage,
|
||||
Image: i,
|
||||
ArangoDBVersion: version,
|
||||
ImageID: testImage,
|
||||
ImageID: i,
|
||||
Enterprise: enterprise,
|
||||
},
|
||||
}
|
||||
|
@ -596,7 +603,7 @@ func (testCase *testCaseStruct) createTestPodData(deployment *Deployment, group
|
|||
var auth string
|
||||
var retries int32 = 720 // one hour divide by 5.
|
||||
if group == api.ServerGroupDBServers {
|
||||
retries = 4320 // 6 hours divide by 5.
|
||||
retries = testProbeDBServerRetires
|
||||
}
|
||||
if deployment.GetSpec().IsAuthenticated() {
|
||||
auth, _ = createTestToken(deployment, testCase, []string{"/_api/version"})
|
||||
|
|
|
@ -135,6 +135,13 @@ func createArangodArgs(cachedStatus interfaces.Inspector, input pod.Input, addit
|
|||
options.Add("--cluster.my-role", "PRIMARY")
|
||||
options.Add("--foxx.queues", false)
|
||||
options.Add("--server.statistics", "true")
|
||||
imageInfo := api.ImageInfo{
|
||||
ArangoDBVersion: input.Version,
|
||||
Enterprise: input.Enterprise,
|
||||
}
|
||||
if IsServerProgressAvailable(input.Group, imageInfo) {
|
||||
options.Add("--server.early-connections", "true")
|
||||
}
|
||||
case api.ServerGroupCoordinators:
|
||||
addAgentEndpoints = true
|
||||
options.Add("--cluster.my-address", myTCPURL)
|
||||
|
|
|
@ -138,17 +138,17 @@ func (a *ArangoDContainer) GetSecurityContext() *core.SecurityContext {
|
|||
func (a *ArangoDContainer) GetProbes() (*core.Probe, *core.Probe, *core.Probe, error) {
|
||||
var liveness, readiness, startup *core.Probe
|
||||
|
||||
probeLivenessConfig, err := a.resources.getLivenessProbe(a.spec, a.group, a.imageInfo.ArangoDBVersion)
|
||||
probeLivenessConfig, err := a.resources.getLivenessProbe(a.spec, a.group, a.imageInfo)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
probeReadinessConfig, err := a.resources.getReadinessProbe(a.spec, a.group, a.imageInfo.ArangoDBVersion)
|
||||
probeReadinessConfig, err := a.resources.getReadinessProbe(a.spec, a.group, a.imageInfo)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
probeStartupConfig, err := a.resources.getStartupProbe(a.spec, a.group, a.imageInfo.ArangoDBVersion)
|
||||
probeStartupConfig, err := a.resources.getStartupProbe(a.spec, a.group, a.imageInfo)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
|
|
@ -21,14 +21,13 @@
|
|||
package resources
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
core "k8s.io/api/core/v1"
|
||||
|
||||
"github.com/arangodb/go-driver"
|
||||
"github.com/arangodb/go-driver/jwt"
|
||||
|
||||
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||
|
@ -51,25 +50,25 @@ type probeCheckBuilder struct {
|
|||
liveness, readiness, startup probeBuilder
|
||||
}
|
||||
|
||||
type probeBuilder func(spec api.DeploymentSpec, group api.ServerGroup, version driver.Version) (Probe, error)
|
||||
type probeBuilder func(spec api.DeploymentSpec, group api.ServerGroup, _ api.ImageInfo) (Probe, error)
|
||||
|
||||
func nilProbeBuilder(spec api.DeploymentSpec, group api.ServerGroup, version driver.Version) (Probe, error) {
|
||||
func nilProbeBuilder(_ api.DeploymentSpec, _ api.ServerGroup, _ api.ImageInfo) (Probe, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *Resources) getReadinessProbe(spec api.DeploymentSpec, group api.ServerGroup, version driver.Version) (Probe, error) {
|
||||
func (r *Resources) getReadinessProbe(spec api.DeploymentSpec, group api.ServerGroup, imageInfo api.ImageInfo) (Probe, error) {
|
||||
if !r.isReadinessProbeEnabled(spec, group) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
builders := r.probeBuilders()
|
||||
builders := r.probeBuilders(imageInfo)
|
||||
|
||||
builder, ok := builders[group]
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
config, err := builder.readiness(spec, group, version)
|
||||
config, err := builder.readiness(spec, group, imageInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -87,19 +86,19 @@ func (r *Resources) getReadinessProbe(spec api.DeploymentSpec, group api.ServerG
|
|||
return config, nil
|
||||
}
|
||||
|
||||
func (r *Resources) getLivenessProbe(spec api.DeploymentSpec, group api.ServerGroup, version driver.Version) (Probe, error) {
|
||||
func (r *Resources) getLivenessProbe(spec api.DeploymentSpec, group api.ServerGroup, imageInfo api.ImageInfo) (Probe, error) {
|
||||
if !r.isLivenessProbeEnabled(spec, group) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
builders := r.probeBuilders()
|
||||
builders := r.probeBuilders(imageInfo)
|
||||
|
||||
builder, ok := builders[group]
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
config, err := builder.liveness(spec, group, version)
|
||||
config, err := builder.liveness(spec, group, imageInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -117,19 +116,19 @@ func (r *Resources) getLivenessProbe(spec api.DeploymentSpec, group api.ServerGr
|
|||
return config, nil
|
||||
}
|
||||
|
||||
func (r *Resources) getStartupProbe(spec api.DeploymentSpec, group api.ServerGroup, version driver.Version) (Probe, error) {
|
||||
func (r *Resources) getStartupProbe(spec api.DeploymentSpec, group api.ServerGroup, imageInfo api.ImageInfo) (Probe, error) {
|
||||
if !r.isStartupProbeEnabled(spec, group) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
builders := r.probeBuilders()
|
||||
builders := r.probeBuilders(imageInfo)
|
||||
|
||||
builder, ok := builders[group]
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
config, err := builder.startup(spec, group, version)
|
||||
config, err := builder.startup(spec, group, imageInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -189,26 +188,26 @@ func (r *Resources) isStartupProbeEnabled(spec api.DeploymentSpec, group api.Ser
|
|||
return probe.CanBeEnabled && probe.EnabledByDefault
|
||||
}
|
||||
|
||||
func (r *Resources) probeBuilders() map[api.ServerGroup]probeCheckBuilder {
|
||||
func (r *Resources) probeBuilders(imageInfo api.ImageInfo) map[api.ServerGroup]probeCheckBuilder {
|
||||
return map[api.ServerGroup]probeCheckBuilder{
|
||||
api.ServerGroupSingle: {
|
||||
startup: r.probeBuilderStartupCoreSelect(),
|
||||
liveness: r.probeBuilderLivenessCoreSelect(),
|
||||
startup: r.probeBuilderStartupCoreSelect(api.ServerGroupSingle, imageInfo),
|
||||
liveness: r.probeBuilderLivenessCoreSelect(api.ServerGroupSingle, imageInfo),
|
||||
readiness: r.probeBuilderReadinessCoreSelect(),
|
||||
},
|
||||
api.ServerGroupAgents: {
|
||||
startup: r.probeBuilderStartupCoreSelect(),
|
||||
liveness: r.probeBuilderLivenessCoreSelect(),
|
||||
startup: r.probeBuilderStartupCoreSelect(api.ServerGroupAgents, imageInfo),
|
||||
liveness: r.probeBuilderLivenessCoreSelect(api.ServerGroupAgents, imageInfo),
|
||||
readiness: r.probeBuilderReadinessSimpleCoreSelect(),
|
||||
},
|
||||
api.ServerGroupDBServers: {
|
||||
startup: r.probeBuilderStartupCoreSelect(),
|
||||
liveness: r.probeBuilderLivenessCoreSelect(),
|
||||
startup: r.probeBuilderStartupCoreSelect(api.ServerGroupDBServers, imageInfo),
|
||||
liveness: r.probeBuilderLivenessCoreSelect(api.ServerGroupDBServers, imageInfo),
|
||||
readiness: r.probeBuilderReadinessSimpleCoreSelect(),
|
||||
},
|
||||
api.ServerGroupCoordinators: {
|
||||
startup: r.probeBuilderStartupCoreSelect(),
|
||||
liveness: r.probeBuilderLivenessCoreSelect(),
|
||||
startup: r.probeBuilderStartupCoreSelect(api.ServerGroupCoordinators, imageInfo),
|
||||
liveness: r.probeBuilderLivenessCoreSelect(api.ServerGroupCoordinators, imageInfo),
|
||||
readiness: r.probeBuilderReadinessCoreSelect(),
|
||||
},
|
||||
api.ServerGroupSyncMasters: {
|
||||
|
@ -224,7 +223,7 @@ func (r *Resources) probeBuilders() map[api.ServerGroup]probeCheckBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
func (r *Resources) probeCommand(spec api.DeploymentSpec, endpoint string) ([]string, error) {
|
||||
func (r *Resources) probeCommand(spec api.DeploymentSpec, probeType api.ProbeType) ([]string, error) {
|
||||
binaryPath, err := os.Executable()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -234,7 +233,8 @@ func (r *Resources) probeCommand(spec api.DeploymentSpec, endpoint string) ([]st
|
|||
exePath,
|
||||
"lifecycle",
|
||||
"probe",
|
||||
fmt.Sprintf("--endpoint=%s", endpoint),
|
||||
string(probeType),
|
||||
// TODO test rotation required when changed
|
||||
}
|
||||
|
||||
if spec.IsSecure() {
|
||||
|
@ -248,40 +248,50 @@ func (r *Resources) probeCommand(spec api.DeploymentSpec, endpoint string) ([]st
|
|||
return args, nil
|
||||
}
|
||||
|
||||
func (r *Resources) probeBuilderLivenessCoreSelect() probeBuilder {
|
||||
if features.JWTRotation().Enabled() {
|
||||
func (r *Resources) probeBuilderLivenessCoreSelect(group api.ServerGroup, imageInfo api.ImageInfo) probeBuilder {
|
||||
if features.JWTRotation().Enabled() || IsServerProgressAvailable(group, imageInfo) {
|
||||
return r.probeBuilderLivenessCoreOperator
|
||||
}
|
||||
|
||||
return r.probeBuilderLivenessCore
|
||||
}
|
||||
|
||||
func (r *Resources) probeBuilderStartupCoreSelect() probeBuilder {
|
||||
if features.JWTRotation().Enabled() {
|
||||
func (r *Resources) probeBuilderStartupCoreSelect(group api.ServerGroup, imageInfo api.ImageInfo) probeBuilder {
|
||||
if features.JWTRotation().Enabled() || IsServerProgressAvailable(group, imageInfo) {
|
||||
return r.probeBuilderStartupCoreOperator
|
||||
}
|
||||
|
||||
return r.probeBuilderStartupCore
|
||||
}
|
||||
|
||||
func (r *Resources) probeBuilderLivenessCoreOperator(spec api.DeploymentSpec, group api.ServerGroup, version driver.Version) (Probe, error) {
|
||||
args, err := r.probeCommand(spec, "/_api/version")
|
||||
func (r *Resources) probeBuilderLivenessCoreOperator(spec api.DeploymentSpec, group api.ServerGroup,
|
||||
image api.ImageInfo) (Probe, error) {
|
||||
args, err := r.probeCommand(spec, api.ProbeTypeLiveness)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &probes.CMDProbeConfig{
|
||||
cmdProbeConfig := &probes.CMDProbeConfig{
|
||||
Command: args,
|
||||
}, nil
|
||||
}
|
||||
if IsServerProgressAvailable(group, image) {
|
||||
cmdProbeConfig.FailureThreshold = math.MaxInt32
|
||||
}
|
||||
|
||||
return cmdProbeConfig, nil
|
||||
}
|
||||
|
||||
func (r *Resources) probeBuilderStartupCoreOperator(spec api.DeploymentSpec, group api.ServerGroup, version driver.Version) (Probe, error) {
|
||||
args, err := r.probeCommand(spec, "/_api/version")
|
||||
func (r *Resources) probeBuilderStartupCoreOperator(spec api.DeploymentSpec, group api.ServerGroup,
|
||||
image api.ImageInfo) (Probe, error) {
|
||||
args, err := r.probeCommand(spec, api.ProbeTypeStartUp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
retries, periodSeconds := getProbeRetries(group)
|
||||
if IsServerProgressAvailable(group, image) {
|
||||
retries = math.MaxInt32
|
||||
}
|
||||
|
||||
return &probes.CMDProbeConfig{
|
||||
Command: args,
|
||||
|
@ -291,7 +301,7 @@ func (r *Resources) probeBuilderStartupCoreOperator(spec api.DeploymentSpec, gro
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (r *Resources) probeBuilderLivenessCore(spec api.DeploymentSpec, group api.ServerGroup, version driver.Version) (Probe, error) {
|
||||
func (r *Resources) probeBuilderLivenessCore(spec api.DeploymentSpec, _ api.ServerGroup, _ api.ImageInfo) (Probe, error) {
|
||||
authorization := ""
|
||||
if spec.IsAuthenticated() {
|
||||
secretData, err := r.getJWTSecret(spec)
|
||||
|
@ -310,7 +320,7 @@ func (r *Resources) probeBuilderLivenessCore(spec api.DeploymentSpec, group api.
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (r *Resources) probeBuilderStartupCore(spec api.DeploymentSpec, group api.ServerGroup, _ driver.Version) (Probe, error) {
|
||||
func (r *Resources) probeBuilderStartupCore(spec api.DeploymentSpec, group api.ServerGroup, _ api.ImageInfo) (Probe, error) {
|
||||
retries, periodSeconds := getProbeRetries(group)
|
||||
|
||||
authorization := ""
|
||||
|
@ -342,8 +352,9 @@ func (r *Resources) probeBuilderReadinessSimpleCoreSelect() probeBuilder {
|
|||
return r.probeBuilderReadinessSimpleCore
|
||||
}
|
||||
|
||||
func (r *Resources) probeBuilderReadinessSimpleCoreOperator(spec api.DeploymentSpec, group api.ServerGroup, version driver.Version) (Probe, error) {
|
||||
p, err := r.probeBuilderReadinessCoreOperator(spec, group, version)
|
||||
func (r *Resources) probeBuilderReadinessSimpleCoreOperator(spec api.DeploymentSpec, group api.ServerGroup,
|
||||
image api.ImageInfo) (Probe, error) {
|
||||
p, err := r.probeBuilderReadinessCoreOperator(spec, group, image)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -360,8 +371,9 @@ func (r *Resources) probeBuilderReadinessSimpleCoreOperator(spec api.DeploymentS
|
|||
return p, nil
|
||||
}
|
||||
|
||||
func (r *Resources) probeBuilderReadinessSimpleCore(spec api.DeploymentSpec, group api.ServerGroup, version driver.Version) (Probe, error) {
|
||||
p, err := r.probeBuilderReadinessCore(spec, group, version)
|
||||
func (r *Resources) probeBuilderReadinessSimpleCore(spec api.DeploymentSpec, group api.ServerGroup,
|
||||
image api.ImageInfo) (Probe, error) {
|
||||
p, err := r.probeBuilderReadinessCore(spec, group, image)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -386,13 +398,8 @@ func (r *Resources) probeBuilderReadinessCoreSelect() probeBuilder {
|
|||
return r.probeBuilderReadinessCore
|
||||
}
|
||||
|
||||
func (r *Resources) probeBuilderReadinessCoreOperator(spec api.DeploymentSpec, _ api.ServerGroup, _ driver.Version) (Probe, error) {
|
||||
// /_admin/server/availability is the way to go, it is available since 3.3.9
|
||||
path := "/_admin/server/availability"
|
||||
if features.FailoverLeadership().Enabled() && r.context.GetMode() == api.DeploymentModeActiveFailover {
|
||||
path = "/_api/version"
|
||||
}
|
||||
args, err := r.probeCommand(spec, path)
|
||||
func (r *Resources) probeBuilderReadinessCoreOperator(spec api.DeploymentSpec, _ api.ServerGroup, _ api.ImageInfo) (Probe, error) {
|
||||
args, err := r.probeCommand(spec, api.ProbeTypeReadiness)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -404,7 +411,7 @@ func (r *Resources) probeBuilderReadinessCoreOperator(spec api.DeploymentSpec, _
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (r *Resources) probeBuilderReadinessCore(spec api.DeploymentSpec, _ api.ServerGroup, _ driver.Version) (Probe, error) {
|
||||
func (r *Resources) probeBuilderReadinessCore(spec api.DeploymentSpec, _ api.ServerGroup, _ api.ImageInfo) (Probe, error) {
|
||||
// /_admin/server/availability is the way to go, it is available since 3.3.9
|
||||
localPath := "/_admin/server/availability"
|
||||
if features.FailoverLeadership().Enabled() && r.context.GetMode() == api.DeploymentModeActiveFailover {
|
||||
|
@ -433,7 +440,7 @@ func (r *Resources) probeBuilderReadinessCore(spec api.DeploymentSpec, _ api.Ser
|
|||
return probeCfg, nil
|
||||
}
|
||||
|
||||
func (r *Resources) probeBuilderLivenessSync(spec api.DeploymentSpec, group api.ServerGroup, version driver.Version) (Probe, error) {
|
||||
func (r *Resources) probeBuilderLivenessSync(spec api.DeploymentSpec, group api.ServerGroup, _ api.ImageInfo) (Probe, error) {
|
||||
authorization := ""
|
||||
port := shared.ArangoSyncMasterPort
|
||||
if group == api.ServerGroupSyncWorkers {
|
||||
|
@ -468,7 +475,7 @@ func (r *Resources) probeBuilderLivenessSync(spec api.DeploymentSpec, group api.
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (r *Resources) probeBuilderStartupSync(spec api.DeploymentSpec, group api.ServerGroup, _ driver.Version) (Probe, error) {
|
||||
func (r *Resources) probeBuilderStartupSync(spec api.DeploymentSpec, group api.ServerGroup, _ api.ImageInfo) (Probe, error) {
|
||||
authorization := ""
|
||||
port := shared.ArangoSyncMasterPort
|
||||
if group == api.ServerGroupSyncWorkers {
|
||||
|
@ -518,3 +525,9 @@ func getProbeRetries(group api.ServerGroup) (int32, int32) {
|
|||
|
||||
return int32(howLong / period), int32(period / time.Second)
|
||||
}
|
||||
|
||||
// IsServerProgressAvailable returns true if server progress is available.
|
||||
func IsServerProgressAvailable(group api.ServerGroup, imageInfo api.ImageInfo) bool {
|
||||
return group == api.ServerGroupDBServers &&
|
||||
features.Version310().Supported(imageInfo.ArangoDBVersion, imageInfo.Enterprise)
|
||||
}
|
||||
|
|
|
@ -105,17 +105,17 @@ func (a *ArangoSyncContainer) GetSecurityContext() *core.SecurityContext {
|
|||
func (a *ArangoSyncContainer) GetProbes() (*core.Probe, *core.Probe, *core.Probe, error) {
|
||||
var liveness, readiness, startup *core.Probe
|
||||
|
||||
probeLivenessConfig, err := a.resources.getLivenessProbe(a.spec, a.group, a.imageInfo.ArangoDBVersion)
|
||||
probeLivenessConfig, err := a.resources.getLivenessProbe(a.spec, a.group, a.imageInfo)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
probeReadinessConfig, err := a.resources.getReadinessProbe(a.spec, a.group, a.imageInfo.ArangoDBVersion)
|
||||
probeReadinessConfig, err := a.resources.getReadinessProbe(a.spec, a.group, a.imageInfo)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
probeStartupConfig, err := a.resources.getReadinessProbe(a.spec, a.group, a.imageInfo.ArangoDBVersion)
|
||||
probeStartupConfig, err := a.resources.getReadinessProbe(a.spec, a.group, a.imageInfo)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue