Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

*: fix user create issue #749

Merged
merged 1 commit into from
Dec 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ COPY utils/ utils/
COPY mysqluser/ mysqluser/

# Build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o manager cmd/manager/main.go
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -oPg manager cmd/manager/main.go

# Use distroless as minimal base image to package the manager binary
# Refer to https://github.com/GoogleContainerTools/distroless for more details
Expand Down
2 changes: 2 additions & 0 deletions api/v1alpha1/mysqluser_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ type UserStatus struct {

// AllowedHosts contains the list of hosts that the user is allowed to connect from.
AllowedHosts []string `json:"allowedHosts,omitempty"`
// Identifies the users changed or not.
Revision string `json:"revision,omitempty"`
}

// MysqlUserConditionType defines the condition types of a MysqlUser resource.
Expand Down
3 changes: 3 additions & 0 deletions charts/mysql-operator/crds/mysql.radondb.com_mysqlusers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,9 @@ spec:
- type
type: object
type: array
revision:
description: Identifies the users changed or not.
type: string
type: object
type: object
served: true
Expand Down
3 changes: 3 additions & 0 deletions config/crd/bases/mysql.radondb.com_mysqlusers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,9 @@ spec:
- type
type: object
type: array
revision:
description: Identifies the users changed or not.
type: string
type: object
type: object
served: true
Expand Down
24 changes: 17 additions & 7 deletions controllers/mysqluser_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,21 +180,31 @@ func (r *MysqlUserReconciler) reconcileUserInDB(ctx context.Context, mysqlUser *
if password == "" {
return fmt.Errorf("the MySQL user's password must not be empty")
}

// Create/Update user in database.
userLog.Info("creating mysql user", "key", mysqlUser.GetKey(), "username", mysqlUser.Spec.User, "cluster", mysqlUser.GetClusterKey())
if err := internal.CreateUserIfNotExists(sqlRunner, mysqlUser.Unwrap(), password); err != nil {
return err
}

// Remove allowed hosts for user.
toRemove := utils.StringDiffIn(mysqlUser.Status.AllowedHosts, mysqlUser.Spec.Hosts)
for _, host := range toRemove {
if err := internal.DropUser(sqlRunner, mysqlUser.Spec.User, host); err != nil {
return err
}
}
// build user management sql and calculate hash.
SQL, err := internal.BuildUserManagementSQL(mysqlUser.Unwrap(), password)
if err != nil {
return err
}
argsToString := fmt.Sprintf("%v", SQL.Args())
SQLhash, err := utils.Hash(SQL.String() + argsToString)
if err == nil && SQLhash == mysqlUser.Status.Revision {
// If the user has not been changed, then skip the following steps.
return nil
}
// Create/Update user in database.
userLog.Info("creating mysql user", "key", mysqlUser.GetKey(), "username", mysqlUser.Spec.User, "cluster", mysqlUser.GetClusterKey())
if err := sqlRunner.QueryExec(SQL); err != nil {
return err
}

mysqlUser.Status.Revision = SQLhash
return nil
}

Expand Down
16 changes: 6 additions & 10 deletions internal/sql_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,15 +333,15 @@ func columnValue(scanArgs []interface{}, slaveCols []string, colName string) str
return string(*scanArgs[columnIndex].(*sql.RawBytes))
}

// CreateUserIfNotExists creates a user if it doesn't already exist and it gives it the specified permissions.
func CreateUserIfNotExists(sqlRunner SQLRunner, user *apiv1alpha1.MysqlUser, pass string) error {
// BuildUserManagementSQL returns a Query that creates a user and grants it permissions.
func BuildUserManagementSQL(user *apiv1alpha1.MysqlUser, pass string) (q Query, err error) {
userName := user.Spec.User
hosts := user.Spec.Hosts
permissions := user.Spec.Permissions

query := Query{}
// Throw error if there are no allowed hosts.
if len(hosts) == 0 {
return errors.New("no allowedHosts specified")
return query, errors.New("no allowedHosts specified")
}

queries := []Query{
Expand All @@ -353,13 +353,9 @@ func CreateUserIfNotExists(sqlRunner SQLRunner, user *apiv1alpha1.MysqlUser, pas
queries = append(queries, permissionsToQuery(permissions, userName, hosts, user.Spec.WithGrantOption))
}

query := BuildAtomicQuery(queries...)
query = BuildAtomicQuery(queries...)

if err := sqlRunner.QueryExec(query); err != nil {
return fmt.Errorf("failed to configure user (user/pass/access), err: %s", err)
}

return nil
return query, nil
}

func getCreateUserQuery(user, pwd string, allowedHosts []string, tlsOption apiv1alpha1.TLSOptions) Query {
Expand Down
13 changes: 13 additions & 0 deletions utils/unsafe.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ limitations under the License.
package utils

import (
"fmt"
"hash/fnv"
"reflect"
"unsafe"

"k8s.io/apimachinery/pkg/util/rand"
)

// BytesToString casts slice to string without copy
Expand Down Expand Up @@ -50,3 +54,12 @@ func StringToBytes(s string) []byte {
sh.Len = len(s)
return b
}

// Caculate hash value of string
func Hash(s string) (string, error) {
hash := fnv.New32()
if _, err := hash.Write([]byte(s)); err != nil {
return "", err
}
return rand.SafeEncodeString(fmt.Sprint(hash.Sum32())), nil
}
15 changes: 15 additions & 0 deletions utils/unsafe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,18 @@ func TestStingToBytes(t *testing.T) {
assert.Equal(t, want, got)
}
}

func TestHash(t *testing.T) {
{
want := "76b587cf9c"
got, err := Hash("SELECT * FROM t2")
assert.NoError(t, err)
assert.Equal(t, want, got)
}
{
want := "76b587cf9c"
got, err := Hash("SELECT * FROM t31")
assert.NoError(t, err)
assert.NotEqual(t, want, got)
}
}