Skip to content

Commit

Permalink
Make k8ssandra-client config builder only available for Cassandra 4.1…
Browse files Browse the repository at this point in the history
… and newer OSS versions
  • Loading branch information
burmanm committed Jul 24, 2023
1 parent e6851a8 commit ac1afe4
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 50 deletions.
5 changes: 5 additions & 0 deletions apis/cassandra/v1beta1/cassandradatacenter_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/Jeffail/gabs/v2"
"github.com/k8ssandra/cass-operator/pkg/serverconfig"
"github.com/pkg/errors"
"golang.org/x/mod/semver"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
Expand Down Expand Up @@ -953,3 +954,7 @@ func (dc *CassandraDatacenter) DatacenterName() string {
}
return dc.Name
}

func (dc *CassandraDatacenter) UseClientImage() bool {
return dc.Spec.ServerType == "cassandra" && semver.Compare(fmt.Sprintf("v%s", dc.Spec.ServerVersion), "v4.1.0") >= 0
}
61 changes: 61 additions & 0 deletions apis/cassandra/v1beta1/cassandradatacenter_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,64 @@ func TestLegacyInternodeDisabled(t *testing.T) {

assert.False(t, dc.LegacyInternodeEnabled())
}

func TestUseClientImage(t *testing.T) {
assert := assert.New(t)

tests := []struct {
serverType string
version string
should bool
}{
{
serverType: "cassandra",
version: "4.1.0",
should: true,
},
{
serverType: "cassandra",
version: "4.1.2",
should: true,
},
{
serverType: "cassandra",
version: "5.0.0",
should: true,
},
{
serverType: "cassandra",
version: "3.11.17",
should: false,
},
{
serverType: "cassandra",
version: "4.0.8",
should: false,
},
{
serverType: "dse",
version: "6.8.39",
should: false,
},
{
serverType: "dse",
version: "4.1.2",
should: false,
},
}

for _, tt := range tests {
dc := CassandraDatacenter{
Spec: CassandraDatacenterSpec{
ServerVersion: tt.version,
ServerType: tt.serverType,
},
}

if tt.should {
assert.True(dc.UseClientImage())
} else {
assert.False(dc.UseClientImage())
}
}
}
2 changes: 1 addition & 1 deletion config/manager/image_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ metadata:
images:
system-logger: "k8ssandra/system-logger:latest"
config-builder: "datastax/cass-config-builder:1.0-ubi7"
k8ssandra-client: "michaelburman290/k8ssandra-client:latest"
k8ssandra-client: "michaelburman290/k8ssandra-client:v0.2.0-dev.cfda014-20230724"
# cassandra:
# "4.0.0": "k8ssandra/cassandra-ubi:latest"
# dse:
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ require (
github.com/Jeffail/gabs/v2 v2.7.0
github.com/onsi/ginkgo/v2 v2.9.4
go.uber.org/zap v1.24.0
golang.org/x/mod v0.12.0
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2
)

Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand Down
106 changes: 62 additions & 44 deletions pkg/reconciliation/construct_podtemplatespec.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
const (
DefaultTerminationGracePeriodSeconds = 120
ServerConfigContainerName = "server-config-init"
ServerBaseConfigContainerName = "server-config-init-base"
CassandraContainerName = "cassandra"
PvcName = "server-data"
SystemLoggerContainerName = "server-system-logger"
Expand Down Expand Up @@ -297,21 +298,24 @@ func addVolumes(dc *api.CassandraDatacenter, baseTemplate *corev1.PodTemplateSpe
},
}

vBaseConfig := corev1.Volume{
Name: "server-config-base",
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
}

vServerLogs := corev1.Volume{
Name: "server-logs",
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
}
volumeDefaults := []corev1.Volume{vServerConfig, vServerLogs}

volumeDefaults := []corev1.Volume{vServerConfig, vBaseConfig, vServerLogs}
if dc.UseClientImage() {
vBaseConfig := corev1.Volume{
Name: "server-config-base",
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
}

volumeDefaults = append(volumeDefaults, vBaseConfig)
}

if addLegacyInternodeMount {
vServerEncryption := corev1.Volume{
Expand Down Expand Up @@ -378,21 +382,23 @@ func buildInitContainers(dc *api.CassandraDatacenter, rackName string, baseTempl

if serverCfg.Image == "" {

if images.GetClientImage() != "" {
serverCfg.Image = images.GetClientImage()
serverCfg.Args = []string{
"config",
"build",
if dc.UseClientImage() {
if images.GetClientImage() != "" {
serverCfg.Image = images.GetClientImage()
serverCfg.Args = []string{
"config",
"build",
}
}
}

/*
} else {
// Use older config-builder
if dc.GetConfigBuilderImage() != "" {
serverCfg.Image = dc.GetConfigBuilderImage()
} else {
serverCfg.Image = images.GetConfigBuilderImage()
}
*/
}

if images.GetImageConfig() != nil && images.GetImageConfig().ImagePullPolicy != "" {
serverCfg.ImagePullPolicy = images.GetImageConfig().ImagePullPolicy
}
Expand All @@ -403,12 +409,42 @@ func buildInitContainers(dc *api.CassandraDatacenter, rackName string, baseTempl
MountPath: "/config",
}

configBaseMount := corev1.VolumeMount{
Name: "server-config-base",
MountPath: "/cassandra-base-config",
configMounts := []corev1.VolumeMount{serverCfgMount}

var configContainer *corev1.Container
if dc.UseClientImage() {

configBaseMount := corev1.VolumeMount{
Name: "server-config-base",
MountPath: "/cassandra-base-config",
}

configMounts = append(configMounts, configBaseMount)

// Similar to k8ssandra 1.x, use config-container if use new config-builder replacement
configContainer = &corev1.Container{
Name: ServerBaseConfigContainerName,
}

if configContainer.Image == "" {
serverImage, err := makeImage(dc)
if err != nil {
return err
}

configContainer.Image = serverImage
if images.GetImageConfig() != nil && images.GetImageConfig().ImagePullPolicy != "" {
configContainer.ImagePullPolicy = images.GetImageConfig().ImagePullPolicy
}

configContainer.Command = []string{"/bin/sh"}
configContainer.Args = []string{"-c", "cp -rf /etc/cassandra/* /cassandra-base-config/"}
}

configContainer.VolumeMounts = []corev1.VolumeMount{configBaseMount}
}

serverCfg.VolumeMounts = combineVolumeMountSlices([]corev1.VolumeMount{serverCfgMount, configBaseMount}, serverCfg.VolumeMounts)
serverCfg.VolumeMounts = combineVolumeMountSlices(configMounts, serverCfg.VolumeMounts)

serverCfg.Resources = *getResourcesOrDefault(&dc.Spec.ConfigBuilderResources, &DefaultsConfigInitContainer)

Expand Down Expand Up @@ -440,32 +476,14 @@ func buildInitContainers(dc *api.CassandraDatacenter, rackName string, baseTempl

serverCfg.Env = combineEnvSlices(envDefaults, serverCfg.Env)

// Similar to k8ssandra 1.x, use config-container..
configContainer := &corev1.Container{
Name: "base-config-init",
}

if configContainer.Image == "" {
serverImage, err := makeImage(dc)
if err != nil {
return err
}

configContainer.Image = serverImage
if images.GetImageConfig() != nil && images.GetImageConfig().ImagePullPolicy != "" {
configContainer.ImagePullPolicy = images.GetImageConfig().ImagePullPolicy
}

configContainer.Command = []string{"/bin/sh"}
configContainer.Args = []string{"-c", "cp -rf /etc/cassandra/* /cassandra-base-config/"}
}

configContainer.VolumeMounts = []corev1.VolumeMount{configBaseMount}

if !foundOverrides {
// Note that append makes a copy, so we must do this after
// serverCfg has been properly set up.
baseTemplate.Spec.InitContainers = append(baseTemplate.Spec.InitContainers, *configContainer, *serverCfg)
if dc.UseClientImage() {
baseTemplate.Spec.InitContainers = append(baseTemplate.Spec.InitContainers, *configContainer, *serverCfg)
} else {
baseTemplate.Spec.InitContainers = append(baseTemplate.Spec.InitContainers, *serverCfg)
}
}

return nil
Expand Down
73 changes: 73 additions & 0 deletions pkg/reconciliation/construct_podtemplatespec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,79 @@ func TestCassandraDatacenter_buildPodTemplateSpec_do_not_propagate_volumes(t *te
assert.True(t, volumeMountsContains(systemLoggerVolumeMounts, volumeMountNameMatcher("server-logs")))
}

func TestCassandraDatacenter_buildPodTemplateSpec_clientImage(t *testing.T) {
assert := assert.New(t)

dc40 := &api.CassandraDatacenter{
Spec: api.CassandraDatacenterSpec{
ClusterName: "bob",
ServerType: "cassandra",
ServerVersion: "4.0.8",
Racks: []api.Rack{
{
Name: "default",
},
},
},
}

dc41 := &api.CassandraDatacenter{
Spec: api.CassandraDatacenterSpec{
ClusterName: "bob",
ServerType: "cassandra",
ServerVersion: "4.1.2",
Racks: []api.Rack{
{
Name: "default",
},
},
},
}

// 4.0 should not have the client image or new config builder, 4.1 should

spec40, err := buildPodTemplateSpec(dc40, dc40.Spec.Racks[0], false, false)
assert.NoError(err, "should not have gotten error when building podTemplateSpec")

initContainers := spec40.Spec.InitContainers

assert.Equal(1, len(initContainers))
assert.Equal(ServerConfigContainerName, initContainers[0].Name)

volumes := spec40.Spec.Volumes
assert.Equal(2, len(volumes))
// We use a contains check here because the ordering is not important
assert.True(volumesContains(volumes, volumeNameMatcher("server-config")))
assert.True(volumesContains(volumes, volumeNameMatcher("server-logs")))

spec41, err := buildPodTemplateSpec(dc41, dc41.Spec.Racks[0], false, false)
assert.NoError(err, "should not have gotten error when building podTemplateSpec")

initContainers = spec41.Spec.InitContainers

assert.Equal(2, len(initContainers))

serverBaseConfigInitContainer := initContainers[0]
assert.Equal(ServerBaseConfigContainerName, serverBaseConfigInitContainer.Name)
assert.Equal(1, len(serverBaseConfigInitContainer.VolumeMounts))
// We use a contains check here because the ordering is not important
assert.True(volumeMountsContains(serverBaseConfigInitContainer.VolumeMounts, volumeMountNameMatcher("server-config-base")))

serverConfigInitContainer := initContainers[1]
assert.Equal(ServerConfigContainerName, serverConfigInitContainer.Name)
assert.Equal(2, len(serverConfigInitContainer.VolumeMounts))
// We use a contains check here because the ordering is not important
assert.True(volumeMountsContains(serverConfigInitContainer.VolumeMounts, volumeMountNameMatcher("server-config")))
assert.True(volumeMountsContains(serverConfigInitContainer.VolumeMounts, volumeMountNameMatcher("server-config-base")))

volumes = spec41.Spec.Volumes
assert.Equal(3, len(volumes))
// We use a contains check here because the ordering is not important
assert.True(volumesContains(volumes, volumeNameMatcher("server-config")))
assert.True(volumesContains(volumes, volumeNameMatcher("server-logs")))
assert.True(volumesContains(volumes, volumeNameMatcher("server-config-base")))
}

func TestCassandraDatacenter_buildPodTemplateSpec_openShift(t *testing.T) {
assert := assert.New(t)

Expand Down
11 changes: 6 additions & 5 deletions pkg/reconciliation/construct_statefulset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,12 +208,13 @@ func TestStatefulSetWithAdditionalVolumesFromSource(t *testing.T) {
sts, err := newStatefulSetForCassandraDatacenter(nil, "r1", dc, 3, false)
assert.NoError(err)

assert.Equal(3, len(sts.Spec.Template.Spec.Volumes))
assert.Equal(4, len(sts.Spec.Template.Spec.Volumes))
assert.Equal("server-config", sts.Spec.Template.Spec.Volumes[0].Name)
assert.Equal("server-logs", sts.Spec.Template.Spec.Volumes[1].Name)
assert.Equal("metrics-config", sts.Spec.Template.Spec.Volumes[2].Name)
assert.NotNil(sts.Spec.Template.Spec.Volumes[2].ConfigMap)
assert.Equal("metrics-config-map", sts.Spec.Template.Spec.Volumes[2].ConfigMap.Name)
assert.Equal("server-config-base", sts.Spec.Template.Spec.Volumes[2].Name)
assert.Equal("metrics-config", sts.Spec.Template.Spec.Volumes[3].Name)
assert.NotNil(sts.Spec.Template.Spec.Volumes[3].ConfigMap)
assert.Equal("metrics-config-map", sts.Spec.Template.Spec.Volumes[3].ConfigMap.Name)

cassandraContainer := findContainer(sts.Spec.Template.Spec.Containers, CassandraContainerName)
assert.NotNil(cassandraContainer)
Expand All @@ -231,7 +232,7 @@ func TestStatefulSetWithAdditionalVolumesFromSource(t *testing.T) {
dc = &api.CassandraDatacenter{
Spec: api.CassandraDatacenterSpec{
ServerType: "cassandra",
ServerVersion: "4.1.0",
ServerVersion: "4.0.8",
ClusterName: "cluster1",
StorageConfig: api.StorageConfig{
CassandraDataVolumeClaimSpec: &corev1.PersistentVolumeClaimSpec{
Expand Down

0 comments on commit ac1afe4

Please sign in to comment.