From be17c70ef87698a22c2b1e77434d56185c430c59 Mon Sep 17 00:00:00 2001 From: jiuker <2818723467@qq.com> Date: Thu, 11 Apr 2024 13:51:50 +0800 Subject: [PATCH] feat: support more type to admin/config/set (#2063) --- pkg/utils/miniojob/minioJob.go | 47 +++++++++++---- pkg/utils/miniojob/minioJob_test.go | 89 +++++++++++++++++++++++------ pkg/utils/miniojob/types.go | 2 +- 3 files changed, 109 insertions(+), 29 deletions(-) diff --git a/pkg/utils/miniojob/minioJob.go b/pkg/utils/miniojob/minioJob.go index 38dac0a4127..843ae866098 100644 --- a/pkg/utils/miniojob/minioJob.go +++ b/pkg/utils/miniojob/minioJob.go @@ -74,17 +74,16 @@ func File(fName string, ext string) FieldsFunc { if args == nil { return out, fmt.Errorf("args is nil") } - for key, val := range args { - if key == fName { - if val == "" { - return out, fmt.Errorf("value is empty") - } - out.FileName = fName - out.FileExt = ext - out.FileContext = strings.TrimSpace(val) - out.ArgType = ArgTypeFile - return out, nil + if val, ok := args[fName]; ok { + if val == "" { + return out, fmt.Errorf("value is empty") } + out.FileName = fName + out.FileExt = ext + out.FileContext = strings.TrimSpace(val) + out.ArgType = ArgTypeFile + delete(args, fName) + return out, nil } return out, fmt.Errorf("file %s not found", fName) } @@ -101,6 +100,7 @@ func KeyValue(key string) FieldsFunc { return out, fmt.Errorf("key %s not found", key) } out.Command = fmt.Sprintf(`%s="%s"`, key, val) + delete(args, key) return out, nil } } @@ -119,6 +119,7 @@ func KeyFile(key string, ext string) FieldsFunc { out.FileExt = ext out.FileContext = strings.TrimSpace(val) out.ArgType = ArgTypeKeyFile + delete(args, key) return out, nil } } @@ -149,10 +150,33 @@ func KeyForamt(key string, format string) FieldsFunc { return out, fmt.Errorf("key %s not found", key) } out.Command = strings.ReplaceAll(format, "$0", strings.ReplaceAll(val, ",", " ")) + delete(args, key) return out, nil } } +// OthersKeyValues - get all the key values +func OthersKeyValues(ignoreFileKeys ...string) FieldsFunc { + return func(args map[string]string) (out Arg, err error) { + if args == nil { + return out, fmt.Errorf("args is nil") + } + data := []string{} + for key, val := range args { + if val != "" { + data = append(data, fmt.Sprintf(`%s="%s"`, key, val)) + } else { + data = append(data, key) + } + delete(args, key) + } + sort.Slice(data, func(i, j int) bool { + return data[i] < data[j] + }) + return Arg{Command: strings.Join(data, " ")}, nil + } +} + // OneOf - one of the funcs must be found // mc admin policy attach OneOf(--user | --group) = mc admin policy attach --user user or mc admin policy attach --group group func OneOf(funcs ...FieldsFunc) FieldsFunc { @@ -214,11 +238,12 @@ var prefixKeyForamt = func(pkey string, ignoreKeys ...string) FieldsFunc { } } } + delete(args, key) } } // avoid flags change the order sort.Slice(data, func(i, j int) bool { - return data[i] > data[j] + return data[i] < data[j] }) return Arg{Command: strings.Join(data, " ")}, nil } diff --git a/pkg/utils/miniojob/minioJob_test.go b/pkg/utils/miniojob/minioJob_test.go index e95d2b3a742..235c2d661c9 100644 --- a/pkg/utils/miniojob/minioJob_test.go +++ b/pkg/utils/miniojob/minioJob_test.go @@ -51,49 +51,49 @@ func TestParser(t *testing.T) { }{ { command: FLAGS("--user"), - args: args, - expect: Arg{Command: "--with-locks --region=us-west-2"}, + args: copyArgs(args), + expect: Arg{Command: "--region=us-west-2 --with-locks"}, expectError: false, }, { command: FLAGS("user"), - args: args, - expect: Arg{Command: "--with-locks --region=us-west-2"}, + args: copyArgs(args), + expect: Arg{Command: "--region=us-west-2 --with-locks"}, expectError: false, }, { command: Key("password"), - args: args, + args: copyArgs(args), expect: Arg{Command: "somepassword"}, expectError: false, }, { command: KeyForamt("user", "--user $0"), - args: args, + args: copyArgs(args), expect: Arg{Command: "--user a b c d"}, expectError: false, }, { command: KeyForamt("user", "--user"), - args: args, + args: copyArgs(args), expect: Arg{Command: "--user a b c d"}, expectError: false, }, { command: ALIAS(), - args: args, + args: copyArgs(args), expect: Arg{Command: "myminio"}, expectError: false, }, { command: Static("test-static"), - args: args, + args: copyArgs(args), expect: Arg{Command: "test-static"}, expectError: false, }, { command: File("policy", "json"), - args: args, + args: copyArgs(args), expect: Arg{ FileName: "policy", FileExt: "json", @@ -117,31 +117,31 @@ func TestParser(t *testing.T) { }, { command: OneOf(KeyForamt("user", "--user"), KeyForamt("group", "--group")), - args: args, + args: copyArgs(args), expect: Arg{Command: "--user a b c d"}, expectError: false, }, { command: OneOf(KeyForamt("miss_user", "--user"), KeyForamt("group", "--group")), - args: args, + args: copyArgs(args), expect: Arg{Command: "--group group1 group2 group3"}, expectError: false, }, { command: OneOf(KeyForamt("miss_user", "--user"), KeyForamt("miss_group", "--group")), - args: args, + args: copyArgs(args), expect: Arg{Command: "--group group1 group2 group3"}, expectError: true, }, { command: Sanitize(ALIAS(), Static("/"), Key("name")), - args: args, + args: copyArgs(args), expect: Arg{Command: "myminio/mybucketName"}, expectError: false, }, } for _, tc := range testCase { - cmd, err := tc.command(args) + cmd, err := tc.command(tc.args) if tc.expectError && err == nil { t.Fatalf("expectCommand error") } @@ -239,7 +239,7 @@ func TestMCConfigSet(t *testing.T) { "client_cert": "cert1", "client_key": "key1", }, - expectCommand: "myminio webhook1 endpoint=\"endpoint1\" auth_token=\"token1\" client_key=\"/temp/client_key.key\" client_cert=\"/temp/client_cert.pem\"", + expectCommand: "myminio webhook1 endpoint=\"endpoint1\" client_key=\"/temp/client_key.key\" client_cert=\"/temp/client_cert.pem\" auth_token=\"token1\"", expectFileNumber: 2, }, { @@ -250,7 +250,7 @@ func TestMCConfigSet(t *testing.T) { "auth_token": "token1", "client_key": "key1", }, - expectCommand: "myminio webhook1 endpoint=\"endpoint1\" auth_token=\"token1\" client_key=\"/temp/client_key.key\"", + expectCommand: "myminio webhook1 endpoint=\"endpoint1\" client_key=\"/temp/client_key.key\" auth_token=\"token1\"", expectFileNumber: 1, }, { @@ -263,6 +263,50 @@ func TestMCConfigSet(t *testing.T) { expectCommand: "myminio webhook1 endpoint=\"endpoint1\" client_key=\"/temp/client_key.key\"", expectFileNumber: 1, }, + { + name: "notify_mysql", + args: map[string]string{ + "webhookName": "notify_mysql", + "dsn_string": "username:password@tcp(mysql.example.com:3306)/miniodb", + "table": "minioevents", + "format": "namespace", + }, + expectCommand: "myminio notify_mysql dsn_string=\"username:password@tcp(mysql.example.com:3306)/miniodb\" format=\"namespace\" table=\"minioevents\"", + expectFileNumber: 0, + }, + { + name: "notify_amqp", + args: map[string]string{ + "webhookName": "notify_amqp:primary", + "url": "user:password@amqp://amqp-endpoint.example.net:5672", + }, + expectCommand: "myminio notify_amqp:primary url=\"user:password@amqp://amqp-endpoint.example.net:5672\"", + expectFileNumber: 0, + }, + { + name: "notify_elasticsearch", + args: map[string]string{ + "webhookName": "notify_elasticsearch:primary", + "url": "user:password@https://elasticsearch-endpoint.example.net:9200", + "index": "bucketevents", + "format": "namespace", + }, + expectCommand: "myminio notify_elasticsearch:primary format=\"namespace\" index=\"bucketevents\" url=\"user:password@https://elasticsearch-endpoint.example.net:9200\"", + expectFileNumber: 0, + }, + { + name: "identity_ldap", + args: map[string]string{ + "webhookName": "identity_ldap", + "enabled": "true", + "server_addr": "ad-ldap.example.net/", + "lookup_bind_dn": "cn=miniolookupuser,dc=example,dc=net", + "lookup_bind_dn_password": "userpassword", + "user_dn_search_base_dn": "dc=example,dc=net", + "user_dn_search_filter": "(&(objectCategory=user)(sAMAccountName=%s))", + }, + expectCommand: "myminio identity_ldap enabled=\"true\" lookup_bind_dn=\"cn=miniolookupuser,dc=example,dc=net\" lookup_bind_dn_password=\"userpassword\" server_addr=\"ad-ldap.example.net/\" user_dn_search_base_dn=\"dc=example,dc=net\" user_dn_search_filter=\"(&(objectCategory=user)(sAMAccountName=%s))\"", + }, } for _, tc := range testCase { command, err := GenerateMinIOIntervalJobCommand(mcCommand, 0, nil, "test", tc.args, funcs) @@ -273,6 +317,9 @@ func TestMCConfigSet(t *testing.T) { if command.Command != tc.expectCommand { t.Fatalf("[%s] expectCommand %s, but got %s", tc.name, tc.expectCommand, command.Command) } + if tc.expectFileNumber != len(command.Files) { + t.Fatalf("[%s] expectFileNumber %d, but got %d", tc.name, tc.expectFileNumber, len(command.Files)) + } } else { if err == nil { t.Fatalf("[%s] expectCommand error", tc.name) @@ -280,3 +327,11 @@ func TestMCConfigSet(t *testing.T) { } } } + +func copyArgs(args map[string]string) map[string]string { + newArgs := make(map[string]string) + for key, val := range args { + newArgs[key] = val + } + return newArgs +} diff --git a/pkg/utils/miniojob/types.go b/pkg/utils/miniojob/types.go index b0ad30fd0f8..a4a4a0f822f 100644 --- a/pkg/utils/miniojob/types.go +++ b/pkg/utils/miniojob/types.go @@ -61,7 +61,7 @@ var JobOperation = map[string][]FieldsFunc{ "admin/user/add": {ALIAS(), Key("user"), Key("password")}, "admin/policy/create": {ALIAS(), Key("name"), File("policy", "json")}, "admin/policy/attach": {ALIAS(), Key("policy"), OneOf(KeyForamt("user", "--user"), KeyForamt("group", "--group"))}, - "admin/config/set": {ALIAS(), Key("webhookName"), Option(KeyValue("endpoint")), Option(KeyValue("auth_token")), Option(KeyFile("client_key", "key")), Option(KeyFile("client_cert", "pem"))}, + "admin/config/set": {ALIAS(), Key("webhookName"), Option(KeyValue("endpoint")), Option(KeyFile("client_key", "key")), Option(KeyFile("client_cert", "pem")), OthersKeyValues()}, } // OperationAliasToMC - convert operation to mc operation