Skip to content

Commit

Permalink
rgw: replace period update --commit with function
Browse files Browse the repository at this point in the history
Replace calls to 'radosgw-admin period update --commit' with an
idempotent function.

Resolves #8879

Signed-off-by: Blaine Gardner <blaine.gardner@redhat.com>
  • Loading branch information
BlaineEXE committed Oct 4, 2021
1 parent 08cb678 commit 6feebee
Show file tree
Hide file tree
Showing 4 changed files with 729 additions and 127 deletions.
86 changes: 86 additions & 0 deletions pkg/operator/ceph/object/admin.go
Expand Up @@ -18,13 +18,16 @@ package object

import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/http/httputil"
"regexp"
"strings"

"github.com/ceph/go-ceph/rgw/admin"
"github.com/coreos/pkg/capnslog"
"github.com/google/go-cmp/cmp"
"github.com/pkg/errors"
cephv1 "github.com/rook/rook/pkg/apis/ceph.rook.io/v1"
"github.com/rook/rook/pkg/clusterd"
Expand Down Expand Up @@ -292,6 +295,89 @@ func isInvalidFlagError(err error) bool {
return exitCode == 22
}

// CommitConfigChanges commits changes to RGW configs for realm/zonegroup/zone changes idempotently.
// Under the hood, this updates the RGW config period and commits the change if changes are detected.
func CommitConfigChanges(c *Context) error {
currentPeriod, err := runAdminCommand(c, true, "period", "get")
if err != nil {
return errorOrIsNotFound(err, "failed to get the current RGW configuration period to see if it needs changed")
}

// this stages the current config changees and returns what the new period config will look like
// without committing the changes
stagedPeriod, err := runAdminCommand(c, true, "period", "update")
if err != nil {
return errorOrIsNotFound(err, "failed to stage the current RGW configuration period")
}

shouldCommit, err := periodWillChange(currentPeriod, stagedPeriod)
if err != nil {
return errors.Wrap(err, "failed to determine if the staged RGW configuration period is different from current")
}

if !shouldCommit {
nsName := fmt.Sprintf("%s/%s", c.clusterInfo.Namespace, c.Name)
logger.Debugf("not committing changes to RGW configuration period for CephObjectStore %q", nsName)
return nil
}
// don't expect json output since we don't intend to use the output from the command
_, err = runAdminCommand(c, false, "period", "update", "--commit")
if err != nil {
return errorOrIsNotFound(err, "failed to commit RGW configuration period changes")
}

return nil
}

// return true if the configuration period will change if the staged period is committed
func periodWillChange(current, staged string) (bool, error) {
var currentJSON map[string]interface{}
var stagedJSON map[string]interface{}
var err error

err = json.Unmarshal([]byte(current), &currentJSON)
if err != nil {
return true, errors.Wrap(err, "failed to unmarshal current RGW configuration period")
}
err = json.Unmarshal([]byte(staged), &stagedJSON)
if err != nil {
return true, errors.Wrap(err, "failed to unmarshal staged RGW configuration period")
}

// There are some values in the periods that we don't care to diff because they are always
// different in the staged period, even when no updates are needed. Sometimes, the values are
// reported as different in the staging output but aren't actually changed upon commit.
ignorePaths := cmp.FilterPath(func(path cmp.Path) bool {
// path.String() outputs nothing for the crude map[string]interface{} JSON struct
// Example of path.GoString() output for a long path in the period JSON:
// root["period_map"].(map[string]interface {})["short_zone_ids"].([]interface {})[0].(map[string]interface {})["val"].(float64)
switch path.GoString() {
case `root["id"]`:
// "id" is always changed in the staged period, but it doesn't always update.
return true
case `root["predecessor_uuid"]`:
// "predecessor_uuid" is always changed in the staged period, but it doesn't always update.
return true
case `root["realm_epoch"]`:
// "realm_epoch" is always incremented in the staged period, but it doesn't always increment.
return true
case `root["epoch"]`:
// Strangely, "epoch" is not incremented in the staged period even though it is always
// incremented upon an actual commit. It could be argued that this behavior is a bug.
// Ignore this value to handle the possibility that the behavior changes in the future.
return true
default:
return false
}
}, cmp.Ignore())

diff := cmp.Diff(currentJSON, stagedJSON, ignorePaths)
diff = strings.TrimSpace(diff)
logger.Debugf("RGW config period diff:\n%s", diff)

return (diff != ""), nil
}

func GetAdminOPSUserCredentials(objContext *Context, spec *cephv1.ObjectStoreSpec) (string, string, error) {
ns := objContext.clusterInfo.Namespace

Expand Down

0 comments on commit 6feebee

Please sign in to comment.