From 629203917b2864e7b973a10b257fb8e3df4c113e Mon Sep 17 00:00:00 2001 From: Jian Qiu Date: Fri, 6 Sep 2024 09:37:03 +0800 Subject: [PATCH] feature: allow generate name with a randome string (#21175) Co-authored-by: Qiu Jian --- pkg/cloudcommon/db/namevalidator.go | 26 ++++++++++++++++++----- pkg/util/stringutils2/namepattern.go | 26 ++++++++++++++++++----- pkg/util/stringutils2/namepattern_test.go | 18 +++++++++++++--- 3 files changed, 57 insertions(+), 13 deletions(-) diff --git a/pkg/cloudcommon/db/namevalidator.go b/pkg/cloudcommon/db/namevalidator.go index 71169db5cd4..e95f3b350fe 100644 --- a/pkg/cloudcommon/db/namevalidator.go +++ b/pkg/cloudcommon/db/namevalidator.go @@ -18,8 +18,10 @@ import ( "context" "fmt" "regexp" + "strings" "yunion.io/x/jsonutils" + "yunion.io/x/pkg/util/seclib" "yunion.io/x/sqlchemy" "yunion.io/x/onecloud/pkg/cloudcommon/consts" @@ -124,7 +126,7 @@ func GenerateAlterName(model IModel, hint string) (string, error) { } func GenerateName2(ctx context.Context, manager IModelManager, ownerId mcclient.IIdentityProvider, hint string, model IModel, baseIndex int) (string, error) { - _, pattern, patternLen, offset := stringutils2.ParseNamePattern2(hint) + _, pattern, patternLen, offset, ch := stringutils2.ParseNamePattern2(hint) var name string if patternLen == 0 { name = hint @@ -132,8 +134,15 @@ func GenerateName2(ctx context.Context, manager IModelManager, ownerId mcclient. if offset > 0 { baseIndex = offset } - name = fmt.Sprintf(pattern, baseIndex) - baseIndex += 1 + switch ch { + case stringutils2.RandomChar: + name = fmt.Sprintf(pattern, strings.ToLower(seclib.RandomPassword(patternLen))) + case stringutils2.RepChar: + fallthrough + default: + name = fmt.Sprintf(pattern, baseIndex) + baseIndex += 1 + } } for { var uniq bool @@ -149,8 +158,15 @@ func GenerateName2(ctx context.Context, manager IModelManager, ownerId mcclient. if uniq { return name, nil } - name = fmt.Sprintf(pattern, baseIndex) - baseIndex += 1 + switch ch { + case stringutils2.RandomChar: + name = fmt.Sprintf(pattern, strings.ToLower(seclib.RandomPassword(patternLen))) + case stringutils2.RepChar: + fallthrough + default: + name = fmt.Sprintf(pattern, baseIndex) + baseIndex += 1 + } } } diff --git a/pkg/util/stringutils2/namepattern.go b/pkg/util/stringutils2/namepattern.go index a14d0fd10d4..04fd1cb1ba4 100644 --- a/pkg/util/stringutils2/namepattern.go +++ b/pkg/util/stringutils2/namepattern.go @@ -20,14 +20,17 @@ import ( "strings" ) +const RepChar = '#' +const RandomChar = '?' + // name## // name##9# -func ParseNamePattern2(name string) (string, string, int, int) { - const RepChar = '#' +func ParseNamePattern2(name string) (string, string, int, int, byte) { var match string var pattern string var patternLen int var offset int + var charType byte start := strings.IndexByte(name, RepChar) if start >= 0 { @@ -45,9 +48,22 @@ func ParseNamePattern2(name string) (string, string, int, int) { } match = fmt.Sprintf("%s%%%s", name[:start], name[end:]) pattern = fmt.Sprintf("%s%%0%dd%s", name[:start], patternLen, name[end:]) + charType = RepChar } else { - match = fmt.Sprintf("%s-%%", name) - pattern = fmt.Sprintf("%s-%%d", name) + start := strings.IndexByte(name, RandomChar) + if start >= 0 { + end := start + 1 + for end < len(name) && name[end] == RandomChar { + end += 1 + } + patternLen = end - start + match = fmt.Sprintf("%s%%%s", name[:start], name[end:]) + pattern = fmt.Sprintf("%s%%s%s", name[:start], name[end:]) + charType = RandomChar + } else { + match = fmt.Sprintf("%s-%%", name) + pattern = fmt.Sprintf("%s-%%d", name) + } } - return match, pattern, patternLen, offset + return match, pattern, patternLen, offset, charType } diff --git a/pkg/util/stringutils2/namepattern_test.go b/pkg/util/stringutils2/namepattern_test.go index 46a76e84f50..d0bab6bfeda 100644 --- a/pkg/util/stringutils2/namepattern_test.go +++ b/pkg/util/stringutils2/namepattern_test.go @@ -25,6 +25,7 @@ func TestParseNamePattern2(t *testing.T) { pattern string patternLen int offset int + charType byte }{ { input: "testimg###", @@ -32,6 +33,7 @@ func TestParseNamePattern2(t *testing.T) { pattern: "testimg%03d", patternLen: 3, offset: 0, + charType: RepChar, }, { input: "testimg###66#", @@ -39,6 +41,7 @@ func TestParseNamePattern2(t *testing.T) { pattern: "testimg%03d", patternLen: 3, offset: 66, + charType: RepChar, }, { input: "testimg###ab#", @@ -46,6 +49,7 @@ func TestParseNamePattern2(t *testing.T) { pattern: "testimg%03d", patternLen: 3, offset: 0, + charType: RepChar, }, { input: "testimg", @@ -54,11 +58,19 @@ func TestParseNamePattern2(t *testing.T) { patternLen: 0, offset: 0, }, + { + input: "testimg???", + match: "testimg%", + pattern: "testimg%s", + patternLen: 3, + offset: 0, + charType: RandomChar, + }, } for _, c := range cases { - m, p, pl, o := ParseNamePattern2(c.input) - if m != c.match || p != c.pattern || pl != c.patternLen || o != c.offset { - t.Errorf("match got %s want %s, pattern got %s want %s, patternLen got %d want %d, offset got %d want %d", m, c.match, p, c.pattern, pl, c.patternLen, o, c.offset) + m, p, pl, o, ch := ParseNamePattern2(c.input) + if m != c.match || p != c.pattern || pl != c.patternLen || o != c.offset || ch != c.charType { + t.Errorf("match got %s want %s, pattern got %s want %s, patternLen got %d want %d, offset got %d want %d, charType got %c want %c", m, c.match, p, c.pattern, pl, c.patternLen, o, c.offset, ch, c.charType) } } }