Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions controllers/operator/appdbreplicaset_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ import (
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/configmap"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/secret"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/service"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/statefulset"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/util/generate"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/util/merge"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/util/result"
Expand All @@ -61,6 +60,7 @@ import (
mekoService "github.com/10gen/ops-manager-kubernetes/pkg/kube/service"
"github.com/10gen/ops-manager-kubernetes/pkg/multicluster"
"github.com/10gen/ops-manager-kubernetes/pkg/placeholders"
"github.com/10gen/ops-manager-kubernetes/pkg/statefulset"
"github.com/10gen/ops-manager-kubernetes/pkg/tls"
"github.com/10gen/ops-manager-kubernetes/pkg/util"
"github.com/10gen/ops-manager-kubernetes/pkg/util/architectures"
Expand Down Expand Up @@ -1892,7 +1892,7 @@ func (r *ReconcileAppDbReplicaSet) deployStatefulSet(ctx context.Context, opsMan
continue
}

if workflowStatus := getStatefulSetStatus(ctx, opsManager.Namespace, opsManager.Spec.AppDB.NameForCluster(memberCluster.Index), memberCluster.Client); !workflowStatus.IsOK() {
if workflowStatus := statefulset.GetStatefulSetStatus(ctx, opsManager.Namespace, opsManager.Spec.AppDB.NameForCluster(memberCluster.Index), memberCluster.Client); !workflowStatus.IsOK() {
return workflowStatus
}

Expand All @@ -1904,7 +1904,7 @@ func (r *ReconcileAppDbReplicaSet) deployStatefulSet(ctx context.Context, opsMan
// if this is the first time deployment, then we need to wait for all stateful sets to become ready after deploying all of them
if scalingFirstTime {
for _, memberCluster := range r.GetHealthyMemberClusters() {
if workflowStatus := getStatefulSetStatus(ctx, opsManager.Namespace, opsManager.Spec.AppDB.NameForCluster(memberCluster.Index), memberCluster.Client); !workflowStatus.IsOK() {
if workflowStatus := statefulset.GetStatefulSetStatus(ctx, opsManager.Namespace, opsManager.Spec.AppDB.NameForCluster(memberCluster.Index), memberCluster.Client); !workflowStatus.IsOK() {
return workflowStatus
}

Expand Down
2 changes: 1 addition & 1 deletion controllers/operator/appdbreplicaset_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ import (
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/automationconfig"
kubernetesClient "github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/client"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/secret"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/statefulset"
"github.com/10gen/ops-manager-kubernetes/pkg/agentVersionManagement"
"github.com/10gen/ops-manager-kubernetes/pkg/dns"
"github.com/10gen/ops-manager-kubernetes/pkg/kube"
"github.com/10gen/ops-manager-kubernetes/pkg/multicluster"
"github.com/10gen/ops-manager-kubernetes/pkg/statefulset"
"github.com/10gen/ops-manager-kubernetes/pkg/util"
"github.com/10gen/ops-manager-kubernetes/pkg/util/env"
)
Expand Down
148 changes: 8 additions & 140 deletions controllers/operator/common_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import (
"encoding/pem"
"fmt"
"reflect"
"strings"
"time"

"github.com/blang/semver"
"github.com/hashicorp/go-multierror"
Expand All @@ -31,7 +29,6 @@ import (
"github.com/10gen/ops-manager-kubernetes/controllers/operator/authentication"
"github.com/10gen/ops-manager-kubernetes/controllers/operator/certs"
"github.com/10gen/ops-manager-kubernetes/controllers/operator/construct"
"github.com/10gen/ops-manager-kubernetes/controllers/operator/inspect"
"github.com/10gen/ops-manager-kubernetes/controllers/operator/secrets"
"github.com/10gen/ops-manager-kubernetes/controllers/operator/watch"
"github.com/10gen/ops-manager-kubernetes/controllers/operator/workflow"
Expand All @@ -40,10 +37,11 @@ import (
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/configmap"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/container"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/secret"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/statefulset"
"github.com/10gen/ops-manager-kubernetes/pkg/agentVersionManagement"
"github.com/10gen/ops-manager-kubernetes/pkg/kube"
"github.com/10gen/ops-manager-kubernetes/pkg/kube/commoncontroller"
"github.com/10gen/ops-manager-kubernetes/pkg/passwordhash"
"github.com/10gen/ops-manager-kubernetes/pkg/statefulset"
"github.com/10gen/ops-manager-kubernetes/pkg/util"
"github.com/10gen/ops-manager-kubernetes/pkg/util/architectures"
"github.com/10gen/ops-manager-kubernetes/pkg/util/env"
Expand All @@ -56,12 +54,6 @@ func automationConfigFirstMsg(resourceType string, valueToSet string) string {
return fmt.Sprintf("About to set `%s` to %s. automationConfig needs to be updated first", resourceType, valueToSet)
}

type patchValue struct {
Op string `json:"op"`
Path string `json:"path"`
Value interface{} `json:"value"`
}

// ReconcileCommonController is the "parent" controller that is included into each specific controller and allows
// to reuse the common functionality
type ReconcileCommonController struct {
Expand Down Expand Up @@ -138,14 +130,7 @@ func ensureRoles(roles []mdbv1.MongoDbRole, conn om.Connection, log *zap.Sugared
// updateStatus updates the status for the CR using patch operation. Note, that the resource status is mutated and
// it's important to pass resource by pointer to all methods which invoke current 'updateStatus'.
func (r *ReconcileCommonController) updateStatus(ctx context.Context, reconciledResource v1.CustomResourceReadWriter, st workflow.Status, log *zap.SugaredLogger, statusOptions ...status.Option) (reconcile.Result, error) {
mergedOptions := append(statusOptions, st.StatusOptions()...)
log.Debugf("Updating status: phase=%v, options=%+v", st.Phase(), mergedOptions)
reconciledResource.UpdateStatus(st.Phase(), mergedOptions...)
if err := r.patchUpdateStatus(ctx, reconciledResource, statusOptions...); err != nil {
log.Errorf("Error updating status to %s: %s", st.Phase(), err)
return reconcile.Result{}, err
}
return st.ReconcileResult()
return commoncontroller.UpdateStatus(ctx, r.client, reconciledResource, st, log, statusOptions...)
}

type WatcherResource interface {
Expand Down Expand Up @@ -200,94 +185,15 @@ func (r *ReconcileCommonController) SetupCommonWatchers(watcherResource WatcherR
}
}

// We fetch a fresh version in case any modifications have been made.
// Note, that this method enforces update ONLY to the status, so the reconciliation events happening because of this
// can be filtered out by 'controller.shouldReconcile'
// The "jsonPatch" merge allows to update only status field
func (r *ReconcileCommonController) patchUpdateStatus(ctx context.Context, resource v1.CustomResourceReadWriter, options ...status.Option) error {
payload := []patchValue{{
Op: "replace",
Path: resource.GetStatusPath(options...),
// in most cases this will be "/status", but for each of the different Ops Manager components
// this will be different
Value: resource.GetStatus(options...),
}}

data, err := json.Marshal(payload)
if err != nil {
return err
}

patch := client.RawPatch(types.JSONPatchType, data)
err = r.client.Status().Patch(ctx, resource, patch)

if err != nil && apiErrors.IsInvalid(err) {
zap.S().Debug("The Status subresource might not exist yet, creating empty subresource")
if err := r.ensureStatusSubresourceExists(ctx, resource, options...); err != nil {
zap.S().Debug("Error from ensuring status subresource: %s", err)
return err
}
return r.client.Status().Patch(ctx, resource, patch)
}

return nil
}

type emptyPayload struct{}

// ensureStatusSubresourceExists ensures that the status subresource section we are trying to write to exists.
// if we just try and patch the full path directly, the subresource sections are not recursively created, so
// we need to ensure that the actual object we're trying to write to exists, otherwise we will get errors.
func (r *ReconcileCommonController) ensureStatusSubresourceExists(ctx context.Context, resource v1.CustomResourceReadWriter, options ...status.Option) error {
fullPath := resource.GetStatusPath(options...)
parts := strings.Split(fullPath, "/")

if strings.HasPrefix(fullPath, "/") {
parts = parts[1:]
}

var path []string
for _, part := range parts {
pathStr := "/" + strings.Join(path, "/")
path = append(path, part)
emptyPatchPayload := []patchValue{{
Op: "add",
Path: pathStr,
Value: emptyPayload{},
}}
data, err := json.Marshal(emptyPatchPayload)
if err != nil {
return err
}
patch := client.RawPatch(types.JSONPatchType, data)
if err := r.client.Status().Patch(ctx, resource, patch); err != nil && !apiErrors.IsInvalid(err) {
return err
}
}
return nil
}

// getResource populates the provided runtime.Object with some additional error handling
func (r *ReconcileCommonController) getResource(ctx context.Context, request reconcile.Request, resource v1.CustomResourceReadWriter, log *zap.SugaredLogger) (reconcile.Result, error) {
err := r.client.Get(ctx, request.NamespacedName, resource)
if err != nil {
if apiErrors.IsNotFound(err) {
// Request object not found, could have been deleted after reconcile request.
// Return and don't requeue
log.Debugf("Object %s doesn't exist, was it deleted after reconcile request?", request.NamespacedName)
return reconcile.Result{}, err
}
// Error reading the object - requeue the request.
log.Errorf("Failed to query object %s: %s", request.NamespacedName, err)
return reconcile.Result{RequeueAfter: 10 * time.Second}, err
}
return reconcile.Result{}, nil
// GetResource populates the provided runtime.Object with some additional error handling
func (r *ReconcileCommonController) GetResource(ctx context.Context, request reconcile.Request, resource v1.CustomResourceReadWriter, log *zap.SugaredLogger) (reconcile.Result, error) {
return commoncontroller.GetResource(ctx, r.client, request, resource, log)
}

// prepareResourceForReconciliation finds the object being reconciled. Returns the reconcile result and any error that
// occurred.
func (r *ReconcileCommonController) prepareResourceForReconciliation(ctx context.Context, request reconcile.Request, resource v1.CustomResourceReadWriter, log *zap.SugaredLogger) (reconcile.Result, error) {
if result, err := r.getResource(ctx, request, resource, log); err != nil {
if result, err := r.GetResource(ctx, request, resource, log); err != nil {
return result, err
}

Expand Down Expand Up @@ -394,38 +300,6 @@ func (r *ReconcileCommonController) scaleStatefulSet(ctx context.Context, namesp
}
}

// getStatefulSetStatus returns the workflow.Status based on the status of the StatefulSet.
// If the StatefulSet is not ready the request will be retried in 3 seconds (instead of the default 10 seconds)
// allowing to reach "ready" status sooner
func getStatefulSetStatus(ctx context.Context, namespace, name string, client kubernetesClient.Client) workflow.Status {
set, err := client.GetStatefulSet(ctx, kube.ObjectKey(namespace, name))
i := 0

// Sometimes it is possible that the StatefulSet which has just been created
// returns a not found error when getting it too soon afterwards.
for apiErrors.IsNotFound(err) && i < 10 {
i++
zap.S().Debugf("StatefulSet was not found: %s, attempt %d", err, i)
time.Sleep(time.Second * 1)
set, err = client.GetStatefulSet(ctx, kube.ObjectKey(namespace, name))
}

if err != nil {
return workflow.Failed(err)
}

if statefulSetState := inspect.StatefulSet(set); !statefulSetState.IsReady() {
return workflow.
Pending("%s", statefulSetState.GetMessage()).
WithResourcesNotReady(statefulSetState.GetResourcesNotReadyStatus()).
WithRetry(3)
} else {
zap.S().Debugf("StatefulSet %s/%s is ready on check attempt #%d, state: %+v: ", namespace, name, i, statefulSetState)
}

return workflow.OK()
}

// validateScram ensures that the SCRAM configuration is valid for the MongoDBResource
func validateScram(mdb *mdbv1.MongoDB, ac *om.AutomationConfig) workflow.Status {
specVersion, err := semver.Make(util.StripEnt(mdb.Spec.GetMongoDBVersion()))
Expand Down Expand Up @@ -943,17 +817,11 @@ func wasCAConfigMapMounted(ctx context.Context, configMapGetter configmap.Getter
return exists
}

type ConfigMapStatefulSetSecretGetter interface {
statefulset.Getter
secret.Getter
configmap.Getter
}

// publishAutomationConfigFirst will check if the Published State of the StatefulSet backed MongoDB Deployments
// needs to be updated first. In the case of unmounting certs, for instance, the certs should be not
// required anymore before we unmount them, or the automation-agent and readiness probe will never
// reach goal state.
func publishAutomationConfigFirst(ctx context.Context, getter ConfigMapStatefulSetSecretGetter, mdb mdbv1.MongoDB, lastSpec *mdbv1.MongoDbSpec, configFunc func(mdb mdbv1.MongoDB) construct.DatabaseStatefulSetOptions, log *zap.SugaredLogger) bool {
func publishAutomationConfigFirst(ctx context.Context, getter kubernetesClient.Client, mdb mdbv1.MongoDB, lastSpec *mdbv1.MongoDbSpec, configFunc func(mdb mdbv1.MongoDB) construct.DatabaseStatefulSetOptions, log *zap.SugaredLogger) bool {
opts := configFunc(mdb)

namespacedName := kube.ObjectKey(mdb.Namespace, opts.GetStatefulSetName())
Expand Down
10 changes: 5 additions & 5 deletions controllers/operator/construct/appdb_construction.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ import (
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/controllers/construct"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/container"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/podtemplatespec"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/statefulset"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/util/merge"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/util/scale"
"github.com/10gen/ops-manager-kubernetes/pkg/kube"
"github.com/10gen/ops-manager-kubernetes/pkg/statefulset"
"github.com/10gen/ops-manager-kubernetes/pkg/tls"
"github.com/10gen/ops-manager-kubernetes/pkg/util"
"github.com/10gen/ops-manager-kubernetes/pkg/util/architectures"
Expand Down Expand Up @@ -303,7 +303,7 @@ func customPersistenceConfig(om *om.MongoDBOpsManager) statefulset.Modification
config = om.Spec.AppDB.PodSpec.Persistence.SingleConfig
}
// Single persistence, needs to modify the only pvc we have
pvcModification := pvcFunc(om.Spec.AppDB.DataVolumeName(), config, *defaultPodSpecPersistence.SingleConfig, om.Labels)
pvcModification := PvcFunc(om.Spec.AppDB.DataVolumeName(), config, *defaultPodSpecPersistence.SingleConfig, om.Labels)

// We already have, by default, the data volume mount,
// here we also create the logs and journal one, as subpath from the same volume
Expand All @@ -327,11 +327,11 @@ func customPersistenceConfig(om *om.MongoDBOpsManager) statefulset.Modification
} else {
// Here need to modify data and logs volumes,
// and create the journal one (which doesn't exist in Community, where this original STS is built)
dataModification := pvcFunc(om.Spec.AppDB.DataVolumeName(), om.Spec.AppDB.PodSpec.Persistence.MultipleConfig.Data, *defaultPodSpecPersistence.MultipleConfig.Data, om.Labels)
logsModification := pvcFunc(om.Spec.AppDB.LogsVolumeName(), om.Spec.AppDB.PodSpec.Persistence.MultipleConfig.Logs, *defaultPodSpecPersistence.MultipleConfig.Logs, om.Labels)
dataModification := PvcFunc(om.Spec.AppDB.DataVolumeName(), om.Spec.AppDB.PodSpec.Persistence.MultipleConfig.Data, *defaultPodSpecPersistence.MultipleConfig.Data, om.Labels)
logsModification := PvcFunc(om.Spec.AppDB.LogsVolumeName(), om.Spec.AppDB.PodSpec.Persistence.MultipleConfig.Logs, *defaultPodSpecPersistence.MultipleConfig.Logs, om.Labels)

journalVolumeMounts := statefulset.CreateVolumeMount(util.PvcNameJournal, util.PvcMountPathJournal)
journalVolumeClaim := pvcFunc(util.PvcNameJournal, om.Spec.AppDB.PodSpec.Persistence.MultipleConfig.Journal, *defaultPodSpecPersistence.MultipleConfig.Journal, om.Labels)
journalVolumeClaim := PvcFunc(util.PvcNameJournal, om.Spec.AppDB.PodSpec.Persistence.MultipleConfig.Journal, *defaultPodSpecPersistence.MultipleConfig.Journal, om.Labels)

return statefulset.Apply(
statefulset.WithVolumeClaim(util.PvcMountPathLogs, journalVolumeClaim),
Expand Down
4 changes: 2 additions & 2 deletions controllers/operator/construct/backup_construction.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ import (
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/podtemplatespec"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/probes"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/secret"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/statefulset"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/util/merge"
"github.com/10gen/ops-manager-kubernetes/pkg/kube"
"github.com/10gen/ops-manager-kubernetes/pkg/multicluster"
"github.com/10gen/ops-manager-kubernetes/pkg/statefulset"
"github.com/10gen/ops-manager-kubernetes/pkg/util"
"github.com/10gen/ops-manager-kubernetes/pkg/vault"
)
Expand Down Expand Up @@ -107,7 +107,7 @@ func backupDaemonStatefulSetFunc(opts OpsManagerStatefulSetOptions) statefulset.
_, configureContainerSecurityContext := podtemplatespec.WithDefaultSecurityContextsModifications()

defaultConfig := common.PersistenceConfig{Storage: util.DefaultHeadDbStorageSize}
pvc := pvcFunc(util.PvcNameHeadDb, opts.HeadDbPersistenceConfig, defaultConfig, opts.Labels)
pvc := PvcFunc(util.PvcNameHeadDb, opts.HeadDbPersistenceConfig, defaultConfig, opts.Labels)
headDbMount := statefulset.CreateVolumeMount(util.PvcNameHeadDb, util.PvcMountPathHeadDb)

caVolumeFunc := podtemplatespec.NOOP()
Expand Down
2 changes: 1 addition & 1 deletion controllers/operator/construct/database_construction.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ import (
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/persistentvolumeclaim"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/podtemplatespec"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/probes"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/statefulset"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/util/merge"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/util/scale"
"github.com/10gen/ops-manager-kubernetes/pkg/kube"
"github.com/10gen/ops-manager-kubernetes/pkg/statefulset"
"github.com/10gen/ops-manager-kubernetes/pkg/util"
"github.com/10gen/ops-manager-kubernetes/pkg/util/architectures"
"github.com/10gen/ops-manager-kubernetes/pkg/util/env"
Expand Down
2 changes: 1 addition & 1 deletion controllers/operator/construct/database_volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (

mdbv1 "github.com/10gen/ops-manager-kubernetes/api/v1/mdb"
"github.com/10gen/ops-manager-kubernetes/controllers/operator/certs"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/statefulset"
"github.com/10gen/ops-manager-kubernetes/pkg/statefulset"
"github.com/10gen/ops-manager-kubernetes/pkg/tls"
"github.com/10gen/ops-manager-kubernetes/pkg/util"
"github.com/10gen/ops-manager-kubernetes/pkg/vault"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ import (
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/podtemplatespec"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/probes"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/secret"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/statefulset"
"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/util/merge"
"github.com/10gen/ops-manager-kubernetes/pkg/kube"
"github.com/10gen/ops-manager-kubernetes/pkg/multicluster"
"github.com/10gen/ops-manager-kubernetes/pkg/statefulset"
"github.com/10gen/ops-manager-kubernetes/pkg/util"
"github.com/10gen/ops-manager-kubernetes/pkg/util/architectures"
"github.com/10gen/ops-manager-kubernetes/pkg/util/env"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package construct
import (
corev1 "k8s.io/api/core/v1"

"github.com/10gen/ops-manager-kubernetes/mongodb-community-operator/pkg/kube/statefulset"
"github.com/10gen/ops-manager-kubernetes/pkg/statefulset"
)

const (
Expand Down
Loading