mirror of
https://github.com/arangodb/kube-arangodb.git
synced 2024-12-14 11:57:37 +00:00
[Feature] Version Check V2 (#1348)
This commit is contained in:
parent
a3206f0c58
commit
44792d2679
15 changed files with 401 additions and 17 deletions
|
@ -8,6 +8,7 @@
|
|||
- (Improvement) Extract Agency Timeout
|
||||
- (Feature) Rebalancer V2
|
||||
- (Bugfix) Fix for ContextExceeded error during backup upload
|
||||
- (Feature) Version Check V2
|
||||
|
||||
## [1.2.30](https://github.com/arangodb/kube-arangodb/tree/1.2.30) (2023-06-16)
|
||||
- (Feature) AgencyCache Interface
|
||||
|
|
1
Makefile
1
Makefile
|
@ -506,6 +506,7 @@ run-unit-tests: $(SOURCES)
|
|||
$(REPOPATH)/pkg/storage \
|
||||
$(REPOPATH)/pkg/crd/... \
|
||||
$(REPOPATH)/pkg/util/... \
|
||||
$(REPOPATH)/cmd/... \
|
||||
$(REPOPATH)/pkg/handlers/...
|
||||
|
||||
# Release building
|
||||
|
|
|
@ -63,6 +63,7 @@ covers individual newer features separately.
|
|||
| Encryption Key Rotation Support | 1.2.0 | > 3.7.0 | Enterprise | 1.0.3 | NotSupported | False | --deployment.feature.encryption-rotation | N/A |
|
||||
| Version Check | 1.1.4 | >= 3.6.0 | Community, Enterprise | 1.1.4 | Alpha | False | --deployment.feature.upgrade-version-check | N/A |
|
||||
| Version Check | 1.2.23 | >= 3.6.0 | Community, Enterprise | 1.1.4 | Production | True | --deployment.feature.upgrade-version-check | N/A |
|
||||
| Version Check V2 | 1.2.31 | >= 3.6.0 | Community, Enterprise | 1.2.31 | Alpha | False | --deployment.feature.upgrade-version-check-v2 | N/A |
|
||||
| Operator Maintenance Management Support | 1.2.0 | >= 3.6.0 | Community, Enterprise | 1.0.7 | Production | True | --deployment.feature.maintenance | N/A |
|
||||
| Graceful Restart | 1.2.5 | >= 3.6.0 | Community, Enterprise | 1.0.7 | Production | True | --deployment.feature.graceful-shutdown | N/A |
|
||||
| Optional Graceful Restart | 1.2.25 | >= 3.6.0 | Community, Enterprise | 1.2.5 | Beta | True | --deployment.feature.optional-graceful-shutdown | N/A |
|
||||
|
|
|
@ -242,6 +242,10 @@ func Execute() int {
|
|||
flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
|
||||
|
||||
if err := cmdMain.Execute(); err != nil {
|
||||
if v, ok := err.(CommandExitCode); ok {
|
||||
return v.ExitCode
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
39
cmd/cmd_exit_code.go
Normal file
39
cmd/cmd_exit_code.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2023 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 cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type CommandExitCode struct {
|
||||
ExitCode int
|
||||
}
|
||||
|
||||
func (c CommandExitCode) Error() string {
|
||||
return fmt.Sprintf("Command exit: %d", c.ExitCode)
|
||||
}
|
||||
|
||||
func Exit(code int) error {
|
||||
return CommandExitCode{
|
||||
ExitCode: code,
|
||||
}
|
||||
}
|
34
cmd/cmd_exit_code_test.go
Normal file
34
cmd/cmd_exit_code_test.go
Normal file
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2023 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 cmd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func ensureExitCode(t *testing.T, err error, code int) {
|
||||
require.Error(t, err)
|
||||
v, ok := err.(CommandExitCode)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, v.ExitCode, code)
|
||||
}
|
99
cmd/init_container_version_check.go
Normal file
99
cmd/init_container_version_check.go
Normal file
|
@ -0,0 +1,99 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2016-2023 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 cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const cmdVersionCheckInitContainersInvalidVersionExitCode = 11
|
||||
|
||||
type cmdVersionCheckInitContainersInputStruct struct {
|
||||
versionPath string
|
||||
|
||||
major, minor int
|
||||
}
|
||||
|
||||
var (
|
||||
cmdVersionCheckInitContainers = &cobra.Command{
|
||||
Use: "version-check",
|
||||
RunE: cmdVersionCheckInitContainersInput.Run,
|
||||
}
|
||||
|
||||
cmdVersionCheckInitContainersInput cmdVersionCheckInitContainersInputStruct
|
||||
)
|
||||
|
||||
type cmdVersionCheckInitContainersData struct {
|
||||
Version int `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdInitContainers.AddCommand(cmdVersionCheckInitContainers)
|
||||
f := cmdVersionCheckInitContainers.Flags()
|
||||
f.StringVar(&cmdVersionCheckInitContainersInput.versionPath, "path", "", "Path to the VERSION file")
|
||||
f.IntVar(&cmdVersionCheckInitContainersInput.major, "major", 0, "Major version of the ArangoDB. 0 if check is disabled")
|
||||
f.IntVar(&cmdVersionCheckInitContainersInput.minor, "minor", 0, "Minor version of the ArangoDB. 0 if check is disabled")
|
||||
}
|
||||
|
||||
func (c cmdVersionCheckInitContainersInputStruct) Run(cmd *cobra.Command, args []string) error {
|
||||
if c.versionPath == "" {
|
||||
return errors.Errorf("Path cannot be empty")
|
||||
}
|
||||
|
||||
if data, err := os.ReadFile(c.versionPath); err != nil {
|
||||
log.Err(err).Msg("File is not readable, continue")
|
||||
return nil
|
||||
} else {
|
||||
major, minor, _, ok := extractVersionFromData(data)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
if c.major != 0 {
|
||||
if c.major != major {
|
||||
return Exit(cmdVersionCheckInitContainersInvalidVersionExitCode)
|
||||
}
|
||||
if c.minor != 0 {
|
||||
if c.minor != minor {
|
||||
return Exit(cmdVersionCheckInitContainersInvalidVersionExitCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func extractVersionFromData(data []byte) (int, int, int, bool) {
|
||||
var c cmdVersionCheckInitContainersData
|
||||
|
||||
if err := json.Unmarshal(data, &c); err != nil {
|
||||
log.Err(err).Msg("Invalid json, continue")
|
||||
return 0, 0, 0, false
|
||||
}
|
||||
|
||||
return c.Version / 10000, c.Version % 10000 / 100, c.Version % 100, true
|
||||
}
|
88
cmd/init_container_version_check_test.go
Normal file
88
cmd/init_container_version_check_test.go
Normal file
|
@ -0,0 +1,88 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2023 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 cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func saveVersionFile(t *testing.T, v int, updates ...func(in *cmdVersionCheckInitContainersInputStruct)) *cmdVersionCheckInitContainersInputStruct {
|
||||
var q cmdVersionCheckInitContainersData
|
||||
|
||||
q.Version = v
|
||||
|
||||
d, err := json.Marshal(q)
|
||||
require.NoError(t, err)
|
||||
|
||||
var n cmdVersionCheckInitContainersInputStruct
|
||||
|
||||
n.versionPath = fmt.Sprintf("%s/VERSION", t.TempDir())
|
||||
|
||||
require.NoError(t, os.WriteFile(n.versionPath, d, 0644))
|
||||
|
||||
for _, u := range updates {
|
||||
u(&n)
|
||||
}
|
||||
|
||||
return &n
|
||||
}
|
||||
|
||||
func Test_extractVersionFromData(t *testing.T) {
|
||||
check := func(valid bool, name string, version int, updates ...func(in *cmdVersionCheckInitContainersInputStruct)) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
err := saveVersionFile(t, version, updates...).Run(nil, nil)
|
||||
if valid {
|
||||
require.NoError(t, err)
|
||||
} else {
|
||||
ensureExitCode(t, err, cmdVersionCheckInitContainersInvalidVersionExitCode)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
check(true, "3.9.10_optional", 30910)
|
||||
|
||||
check(true, "3.9.10_required_major", 30910, func(in *cmdVersionCheckInitContainersInputStruct) {
|
||||
in.major = 3
|
||||
})
|
||||
|
||||
check(true, "3.9.10_required_minor", 30910, func(in *cmdVersionCheckInitContainersInputStruct) {
|
||||
in.major = 3
|
||||
in.minor = 9
|
||||
})
|
||||
|
||||
check(false, "3.9.10_required_major_mismatch", 30910, func(in *cmdVersionCheckInitContainersInputStruct) {
|
||||
in.major = 4
|
||||
})
|
||||
|
||||
check(false, "3.9.10_required_minor_mismatch", 30910, func(in *cmdVersionCheckInitContainersInputStruct) {
|
||||
in.major = 3
|
||||
in.minor = 5
|
||||
})
|
||||
|
||||
check(true, "3.9.10_required_minor_only_mismatch", 30910, func(in *cmdVersionCheckInitContainersInputStruct) {
|
||||
in.minor = 5
|
||||
})
|
||||
}
|
37
cmd/init_containers.go
Normal file
37
cmd/init_containers.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2023 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 cmd
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
var (
|
||||
cmdInitContainers = &cobra.Command{
|
||||
Use: "init-containers",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
},
|
||||
Hidden: true,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmdMain.AddCommand(cmdInitContainers)
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
|
||||
// Copyright 2016-2023 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.
|
||||
|
@ -22,6 +22,7 @@ package features
|
|||
|
||||
func init() {
|
||||
registerFeature(upgradeVersionCheck)
|
||||
registerFeature(upgradeVersionCheckV2)
|
||||
}
|
||||
|
||||
var upgradeVersionCheck Feature = &feature{
|
||||
|
@ -32,6 +33,18 @@ var upgradeVersionCheck Feature = &feature{
|
|||
enabledByDefault: true,
|
||||
}
|
||||
|
||||
var upgradeVersionCheckV2 Feature = &feature{
|
||||
name: "upgrade-version-check-v2",
|
||||
description: "Enable initContainer with pre version check based by Operator",
|
||||
version: "3.6.0",
|
||||
enterpriseRequired: false,
|
||||
enabledByDefault: true,
|
||||
}
|
||||
|
||||
func UpgradeVersionCheck() Feature {
|
||||
return upgradeVersionCheck
|
||||
}
|
||||
|
||||
func UpgradeVersionCheckV2() Feature {
|
||||
return upgradeVersionCheckV2
|
||||
}
|
||||
|
|
|
@ -470,13 +470,18 @@ func (m *MemberArangoDPod) GetInitContainers(cachedStatus interfaces.Inspector)
|
|||
|
||||
// VersionCheck Container
|
||||
{
|
||||
versionArgs := pod.UpgradeVersionCheck().Args(m.AsInput())
|
||||
if len(versionArgs) > 0 {
|
||||
switch m.group {
|
||||
case api.ServerGroupAgents, api.ServerGroupDBServers, api.ServerGroupSingle:
|
||||
if features.UpgradeVersionCheckV2().Enabled() {
|
||||
c := k8sutil.ArangodVersionCheckInitContainer(api.ServerGroupReservedInitContainerNameVersionCheck, executable, m.resources.context.GetOperatorImage(),
|
||||
m.imageInfo.ArangoDBVersion, m.groupSpec.SecurityContext.NewSecurityContext())
|
||||
initContainers = append(initContainers, c)
|
||||
} else if features.UpgradeVersionCheck().Enabled() {
|
||||
upgradeContainer := &ArangoVersionCheckContainer{
|
||||
m.GetContainerCreator(),
|
||||
cachedStatus,
|
||||
m.AsInput(),
|
||||
versionArgs,
|
||||
pod.UpgradeVersionCheck().Args(m.AsInput()),
|
||||
}
|
||||
|
||||
c, err := k8sutil.NewContainer(upgradeContainer)
|
||||
|
@ -488,6 +493,7 @@ func (m *MemberArangoDPod) GetInitContainers(cachedStatus interfaces.Inspector)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return initContainers, nil
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
|
||||
// Copyright 2016-2023 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.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
|
||||
// Copyright 2016-2023 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.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
|
||||
// Copyright 2016-2023 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.
|
||||
|
|
61
pkg/util/k8sutil/version_check.go
Normal file
61
pkg/util/k8sutil/version_check.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2023 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 k8sutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
core "k8s.io/api/core/v1"
|
||||
|
||||
"github.com/arangodb/go-driver"
|
||||
|
||||
"github.com/arangodb/kube-arangodb/pkg/apis/shared"
|
||||
)
|
||||
|
||||
// ArangodVersionCheckInitContainer creates a container configured to check version.
|
||||
func ArangodVersionCheckInitContainer(name, executable, operatorImage string, version driver.Version, securityContext *core.SecurityContext) core.Container {
|
||||
versionFile := filepath.Join(shared.ArangodVolumeMountDir, "VERSION-1")
|
||||
var command = []string{
|
||||
executable,
|
||||
"init-containers",
|
||||
"version-check",
|
||||
"--path",
|
||||
versionFile,
|
||||
}
|
||||
|
||||
if v := version.Major(); v > 0 {
|
||||
command = append(command,
|
||||
"--major",
|
||||
fmt.Sprintf("%d", v))
|
||||
|
||||
if v := version.Minor(); v > 0 {
|
||||
command = append(command,
|
||||
"--minor",
|
||||
fmt.Sprintf("%d", v))
|
||||
}
|
||||
}
|
||||
|
||||
volumes := []core.VolumeMount{
|
||||
ArangodVolumeMount(),
|
||||
}
|
||||
return operatorInitContainer(name, operatorImage, command, securityContext, volumes)
|
||||
}
|
Loading…
Reference in a new issue