Skip to content

Commit

Permalink
Add OperatorConfig option to indicate deployment with OLM (#547)
Browse files Browse the repository at this point in the history
* Modify bundle creation to set olmDeployment = true in the OperatorConfig. If cass-operator has this configuration parameter set, it will set a default serviceAccount to cass-operator-cassandra-default-sa

* Wire olmDeployment config property to mean deployed in Openshift to the ReconciliationContext

* Apply defaultServiceAccount when creating StatefulSet when running under OpenShift

* Enable in main.go the OperatorConfig
  • Loading branch information
burmanm authored Jun 30, 2023
1 parent cd5709a commit 640a4db
Show file tree
Hide file tree
Showing 19 changed files with 173 additions and 58 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Changelog for Cass Operator, new PRs should update the `main / unreleased` secti
* [CHANGE] [#542](https://github.com/k8ssandra/cass-operator/issues/542) Support 7.x.x version numbers for DSE and 5.x.x for Cassandra
* [CHANGE] [#531](https://github.com/k8ssandra/cass-operator/issues/531) Update to Kubebuilder gov4-alpha layout structure
* [ENHANCEMENT] [#523](https://github.com/k8ssandra/cass-operator/issues/516) Spec.ServiceAccountName is introduced as replacements to Spec.ServiceAccount (to account for naming changes in Kubernetes itself), also PodTemplateSpec.Spec.ServiceAccountName is supported. Precendence order is: Spec.ServiceAccountName > Spec.ServiceAccount > PodTemplateSpec.
* [ENHANCEMENT] [#541](https://github.com/k8ssandra/cass-operator/issues/541) When deployed through OLM, add serviceAccount to Cassandra pods that use nonroot priviledge
* [CHANGE] [#516](https://github.com/k8ssandra/cass-operator/issues/516) Modify sidecar default CPU and memory limits.
* [CHANGE] [#495](https://github.com/k8ssandra/cass-operator/issues/495) Remove all the VMware PSP specific code from the codebase. This has been inoperational since 1.8.0
* [CHANGE] [#494](https://github.com/k8ssandra/cass-operator/issues/494) Remove deprecated generated clientsets.
Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,8 @@ endif
bundle: manifests kustomize operator-sdk ## Generate bundle manifests and metadata, then validate generated files.
$(OPSDK) generate kustomize manifests -q
cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG)
$(KUSTOMIZE) build --load-restrictor LoadRestrictionsNone config/manifests | $(OPSDK) generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)
scripts/preprocess-bundle.sh
$(KUSTOMIZE) build --load-restrictor LoadRestrictionsNone config/manifests | $(OPSDK) generate bundle -q --overwrite --extra-service-accounts cass-operator-cassandra-default-sa --version $(VERSION) $(BUNDLE_METADATA_OPTS)
scripts/postprocess-bundle.sh
$(OPSDK) bundle validate ./bundle --select-optional suite=operatorframework

Expand Down
3 changes: 3 additions & 0 deletions apis/config/v1beta1/operatorconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ type OperatorConfig struct {

// ImageConfigFile indicates the path where to load the imageConfig from
ImageConfigFile string `json:"imageConfigFile,omitempty"`

// OLMDeployed is set to true when operator is deployed through OLM. This will activate additional Openshift features
OLMDeployed bool `json:"olmDeployment,omitempty"`
}

func init() {
Expand Down
9 changes: 5 additions & 4 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,11 @@ func main() {
}

if err = (&controllers.CassandraDatacenterReconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("CassandraDatacenter"),
Scheme: mgr.GetScheme(),
Recorder: mgr.GetEventRecorderFor("cass-operator"),
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("CassandraDatacenter"),
Scheme: mgr.GetScheme(),
Recorder: mgr.GetEventRecorderFor("cass-operator"),
OperatorConfig: &operConfig,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "CassandraDatacenter")
os.Exit(1)
Expand Down
1 change: 1 addition & 0 deletions config/components/webhook/controller_manager_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ leaderElection:
resourceName: b569adb7.cassandra.datastax.com
disableWebhooks: false
imageConfigFile: /configs/image_config.yaml
olmDeployment: false
1 change: 1 addition & 0 deletions config/manager/controller_manager_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ leaderElection:
resourceName: b569adb7.cassandra.datastax.com
disableWebhooks: true
imageConfigFile: /configs/image_config.yaml
olmDeployment: false
25 changes: 25 additions & 0 deletions config/rbac/nonroot_role.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: cassandra-nonroot
rules:
- apiGroups:
- security.openshift.io
resourceNames:
- nonroot
resources:
- securitycontextconstraints
verbs:
- use
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: cassandra-nonroot-rolebinding
subjects:
- kind: ServiceAccount
name: cassandra-default-sa
roleRef:
kind: Role
name: cassandra-nonroot
apiGroup: rbac.authorization.k8s.io
4 changes: 4 additions & 0 deletions config/rbac/service_account_nonroot.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: cassandra-default-sa
1 change: 0 additions & 1 deletion config/samples/example-cassdc-three-nodes-single-rack.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ spec:
resources:
requests:
storage: 10Gi
dockerImageRunsAsCassandra: false
resources:
requests:
memory: 2Gi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/source"

api "github.com/k8ssandra/cass-operator/apis/cassandra/v1beta1"
configv1beta1 "github.com/k8ssandra/cass-operator/apis/config/v1beta1"
)

// datastax.com groups
Expand All @@ -70,6 +71,9 @@ type CassandraDatacenterReconciler struct {
// during reconciliation where we update the mappings for the watches.
// Putting it here allows us to get it to both places.
SecretWatches dynamicwatch.DynamicWatches

// OperatorConfig allows Reconciler to access generic configuration properties
OperatorConfig *configv1beta1.OperatorConfig
}

// Reconcile reads that state of the cluster for a Datacenter object
Expand Down Expand Up @@ -100,7 +104,7 @@ func (r *CassandraDatacenterReconciler) Reconcile(ctx context.Context, request c

logger.Info("======== handler::Reconcile has been called")

rc, err := reconciliation.CreateReconciliationContext(ctx, &request, r.Client, r.Scheme, r.Recorder, r.SecretWatches)
rc, err := reconciliation.CreateReconciliationContext(ctx, &request, r.Client, r.Scheme, r.Recorder, r.SecretWatches, r.OperatorConfig.OLMDeployed)

if err != nil {
if errors.IsNotFound(err) {
Expand Down
6 changes: 5 additions & 1 deletion pkg/reconciliation/construct_podtemplatespec.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const (
CassandraContainerName = "cassandra"
PvcName = "server-data"
SystemLoggerContainerName = "server-system-logger"
OpenShiftPodServiceAccount = "cass-operator-cassandra-default-sa"
)

// calculateNodeAffinity provides a way to decide where to schedule pods within a statefulset based on labels
Expand Down Expand Up @@ -663,7 +664,7 @@ func buildContainers(dc *api.CassandraDatacenter, baseTemplate *corev1.PodTempla
return nil
}

func buildPodTemplateSpec(dc *api.CassandraDatacenter, rack api.Rack, addLegacyInternodeMount bool) (*corev1.PodTemplateSpec, error) {
func buildPodTemplateSpec(dc *api.CassandraDatacenter, rack api.Rack, addLegacyInternodeMount, openShift bool) (*corev1.PodTemplateSpec, error) {

baseTemplate := dc.Spec.PodTemplateSpec.DeepCopy()

Expand All @@ -672,6 +673,9 @@ func buildPodTemplateSpec(dc *api.CassandraDatacenter, rack api.Rack, addLegacyI
}

// Service Account
if openShift {
baseTemplate.Spec.ServiceAccountName = OpenShiftPodServiceAccount
}

if dc.Spec.ServiceAccountName != "" {
baseTemplate.Spec.ServiceAccountName = dc.Spec.ServiceAccountName
Expand Down
60 changes: 47 additions & 13 deletions pkg/reconciliation/construct_podtemplatespec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,7 @@ func TestCassandraDatacenter_buildPodTemplateSpec_containers_merge(t *testing.T)
},
},
}
got, err := buildPodTemplateSpec(dc, dc.Spec.Racks[0], false)
got, err := buildPodTemplateSpec(dc, dc.Spec.Racks[0], false, false)

assert.NoError(t, err, "should not have gotten error when building podTemplateSpec")
assert.Equal(t, 3, len(got.Spec.Containers))
Expand Down Expand Up @@ -604,7 +604,7 @@ func TestCassandraDatacenter_buildPodTemplateSpec_initcontainers_merge(t *testin
ConfigBuilderResources: testContainer.Resources,
},
}
got, err := buildPodTemplateSpec(dc, dc.Spec.Racks[0], false)
got, err := buildPodTemplateSpec(dc, dc.Spec.Racks[0], false, false)

assert.NoError(t, err, "should not have gotten error when building podTemplateSpec")
assert.Equal(t, 2, len(got.Spec.InitContainers))
Expand Down Expand Up @@ -647,7 +647,7 @@ func TestCassandraDatacenter_buildPodTemplateSpec_add_initContainer_after_config
},
}

podTemplateSpec, err := buildPodTemplateSpec(dc, dc.Spec.Racks[0], false)
podTemplateSpec, err := buildPodTemplateSpec(dc, dc.Spec.Racks[0], false, false)

assert.NoError(t, err, "should not have gotten error when building podTemplateSpec")

Expand Down Expand Up @@ -708,7 +708,7 @@ func TestCassandraDatacenter_buildPodTemplateSpec_add_initContainer_with_volumes
},
}

podTemplateSpec, err := buildPodTemplateSpec(dc, dc.Spec.Racks[0], true)
podTemplateSpec, err := buildPodTemplateSpec(dc, dc.Spec.Racks[0], true, false)

assert.NoError(t, err, "should not have gotten error when building podTemplateSpec")

Expand Down Expand Up @@ -817,7 +817,7 @@ func TestCassandraDatacenter_buildPodTemplateSpec_add_container_with_volumes(t *
},
}

podTemplateSpec, err := buildPodTemplateSpec(dc, dc.Spec.Racks[0], true)
podTemplateSpec, err := buildPodTemplateSpec(dc, dc.Spec.Racks[0], true, false)

assert.NoError(t, err, "should not have gotten error when building podTemplateSpec")

Expand Down Expand Up @@ -873,7 +873,7 @@ func TestCassandraDatacenter_buildPodTemplateSpec_add_container_with_volumes(t *
testZoneRack := dc.Spec.Racks[0]
testZoneRack.NodeAffinityLabels = map[string]string{zoneLabel: "testzone"}
dc.Spec.Racks[0] = testZoneRack
podTemplateSpec, err = buildPodTemplateSpec(dc, testZoneRack, false)
podTemplateSpec, err = buildPodTemplateSpec(dc, testZoneRack, false, false)
assert.NoError(t, err, "should not have gotten error when building podTemplateSpec")

volumes = podTemplateSpec.Spec.Volumes
Expand Down Expand Up @@ -973,7 +973,7 @@ func TestCassandraDatacenter_buildPodTemplateSpec_labels_merge(t *testing.T) {
}
dc.Spec.PodTemplateSpec.Labels = map[string]string{"abc": "123"}

spec, err := buildPodTemplateSpec(dc, dc.Spec.Racks[0], false)
spec, err := buildPodTemplateSpec(dc, dc.Spec.Racks[0], false, false)
got := spec.Labels

expected := dc.GetRackLabels("testrack")
Expand Down Expand Up @@ -1007,7 +1007,7 @@ func TestCassandraDatacenter_buildContainers_additional_labels(t *testing.T) {
}
dc.Spec.PodTemplateSpec.Labels = map[string]string{"abc": "123"}

spec, err := buildPodTemplateSpec(dc, dc.Spec.Racks[0], false)
spec, err := buildPodTemplateSpec(dc, dc.Spec.Racks[0], false, false)
got := spec.Labels

expected := dc.GetRackLabels("testrack")
Expand Down Expand Up @@ -1048,7 +1048,7 @@ func TestCassandraDatacenter_buildPodTemplateSpec_overrideSecurityContext(t *tes
},
}

spec, err := buildPodTemplateSpec(dc, dc.Spec.Racks[0], false)
spec, err := buildPodTemplateSpec(dc, dc.Spec.Racks[0], false, false)

assert.NoError(t, err, "should not have gotten an error when building podTemplateSpec")
assert.NotNil(t, spec)
Expand Down Expand Up @@ -1100,7 +1100,7 @@ func TestCassandraDatacenter_buildPodTemplateSpec_do_not_propagate_volumes(t *te
},
}

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

initContainers := spec.Spec.InitContainers
Expand Down Expand Up @@ -1133,6 +1133,40 @@ func TestCassandraDatacenter_buildPodTemplateSpec_do_not_propagate_volumes(t *te
assert.True(t, volumeMountsContains(systemLoggerVolumeMounts, volumeMountNameMatcher("server-logs")))
}

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

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

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

assert.Equal(spec.Spec.ServiceAccountName, "", "no default serviceAccount is set")

spec, err = buildPodTemplateSpec(dc, dc.Spec.Racks[0], true, true)
assert.NoError(err, "should not have gotten error when building podTemplateSpec")

assert.Equal(spec.Spec.ServiceAccountName, OpenShiftPodServiceAccount, "missing serviceAccount when running under OLM")

dc.Spec.ServiceAccountName = "overrideSA"

spec, err = buildPodTemplateSpec(dc, dc.Spec.Racks[0], true, true)
assert.NoError(err, "should not have gotten error when building podTemplateSpec")

assert.Equal(spec.Spec.ServiceAccountName, "overrideSA", "under OLM the serviceAccountName must be overwritable")
}

func TestCassandraDatacenter_buildContainers_DisableSystemLoggerSidecar(t *testing.T) {
dc := &api.CassandraDatacenter{
Spec: api.CassandraDatacenterSpec{
Expand Down Expand Up @@ -1323,7 +1357,7 @@ func TestTolerations(t *testing.T) {
},
}

spec, err := buildPodTemplateSpec(dc, dc.Spec.Racks[0], false)
spec, err := buildPodTemplateSpec(dc, dc.Spec.Racks[0], false, false)

assert.NoError(t, err, "failed to build PodTemplateSpec")
// using ElementsMatch instead of Equal because we do not really care about ordering.
Expand Down Expand Up @@ -1360,7 +1394,7 @@ func TestTolerations(t *testing.T) {
},
}

spec, err = buildPodTemplateSpec(dc, dc.Spec.Racks[0], false)
spec, err = buildPodTemplateSpec(dc, dc.Spec.Racks[0], false, false)

assert.NoError(t, err, "failed to build PodTemplateSpec")
// using ElementsMatch instead of Equal because we do not really care about ordering.
Expand Down Expand Up @@ -1580,7 +1614,7 @@ func TestServiceAccountPrecedence(t *testing.T) {
}

for _, test := range tests {
pds, err := buildPodTemplateSpec(test.dc, test.dc.Spec.Racks[0], false)
pds, err := buildPodTemplateSpec(test.dc, test.dc.Spec.Racks[0], false, false)
assert.NoError(err)
assert.Equal(test.accountName, pds.Spec.ServiceAccountName)
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/reconciliation/construct_statefulset.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ func newStatefulSetForCassandraDatacenter(
sts *appsv1.StatefulSet,
rackName string,
dc *api.CassandraDatacenter,
replicaCount int) (*appsv1.StatefulSet, error) {
replicaCount int,
openShift bool) (*appsv1.StatefulSet, error) {

replicaCountInt32 := int32(replicaCount)

Expand Down Expand Up @@ -126,7 +127,7 @@ func newStatefulSetForCassandraDatacenter(

nsName := newNamespacedNameForStatefulSet(dc, rackName)

template, err := buildPodTemplateSpec(dc, rack, legacyInternodeMount(dc, sts))
template, err := buildPodTemplateSpec(dc, rack, legacyInternodeMount(dc, sts), openShift)
if err != nil {
return nil, err
}
Expand Down
Loading

0 comments on commit 640a4db

Please sign in to comment.