diff --git a/pkg/apiserver/domain/model/system_info.go b/pkg/apiserver/domain/model/system_info.go index 0092153c1..4231e33ad 100644 --- a/pkg/apiserver/domain/model/system_info.go +++ b/pkg/apiserver/domain/model/system_info.go @@ -32,11 +32,12 @@ const ( // SystemInfo systemInfo model type SystemInfo struct { BaseModel - InstallID string `json:"installID"` - EnableCollection bool `json:"enableCollection"` - StatisticInfo StatisticInfo `json:"statisticInfo,omitempty"` - LoginType string `json:"loginType"` - DexUserDefaultProjects []ProjectRef `json:"projects"` + InstallID string `json:"installID"` + EnableCollection bool `json:"enableCollection"` + StatisticInfo StatisticInfo `json:"statisticInfo,omitempty"` + LoginType string `json:"loginType"` + DexUserDefaultProjects []ProjectRef `json:"projects"` + DexUserDefaultPlatformRoles []string `json:"dexUserDefaultPlatformRoles"` } // ProjectRef set the project name and roles diff --git a/pkg/apiserver/domain/service/authentication.go b/pkg/apiserver/domain/service/authentication.go index f54d187e8..3bb08399e 100644 --- a/pkg/apiserver/domain/service/authentication.go +++ b/pkg/apiserver/domain/service/authentication.go @@ -484,6 +484,10 @@ func (d *dexHandlerImpl) login(ctx context.Context) (*apisv1.UserBase, error) { } userBase = convertUserBase(u) } else { + systemInfo, err := d.systemInfoService.GetSystemInfo(ctx) + if err != nil { + log.Logger.Errorf("failed to get the system info %s", err.Error()) + } user := &model.User{ Email: claims.Email, Name: strings.ToLower(claims.Sub), @@ -491,18 +495,17 @@ func (d *dexHandlerImpl) login(ctx context.Context) (*apisv1.UserBase, error) { Alias: claims.Name, LastLoginTime: time.Now(), } + if systemInfo != nil { + user.UserRoles = systemInfo.DexUserDefaultPlatformRoles + } if err := d.Store.Add(ctx, user); err != nil { log.Logger.Errorf("failed to save the user from the dex: %s", err.Error()) return nil, err } - systemInfo, err := d.systemInfoService.GetSystemInfo(ctx) - if err != nil { - log.Logger.Errorf("failed to get the system info %s", err.Error()) - } if systemInfo != nil { for _, project := range systemInfo.DexUserDefaultProjects { _, err := d.projectService.AddProjectUser(ctx, project.Name, apisv1.AddProjectUserRequest{ - UserName: claims.Sub, + UserName: strings.ToLower(claims.Sub), UserRoles: project.Roles, }) if err != nil { diff --git a/pkg/apiserver/domain/service/authentication_test.go b/pkg/apiserver/domain/service/authentication_test.go index 657c8fb11..d227f68bc 100644 --- a/pkg/apiserver/domain/service/authentication_test.go +++ b/pkg/apiserver/domain/service/authentication_test.go @@ -23,6 +23,7 @@ import ( "io/ioutil" "reflect" "strconv" + "strings" "time" . "github.com/agiledragon/gomonkey/v2" @@ -65,7 +66,7 @@ var _ = Describe("Test authentication service functions", func() { }) It("Test Dex login", func() { testIDToken := &oidc.IDToken{} - sub := "248289761001" + sub := "248289761001Abv" patch := ApplyMethod(reflect.TypeOf(testIDToken), "Claims", func(_ *oidc.IDToken, v interface{}) error { return json.Unmarshal([]byte(fmt.Sprintf(`{"email":"test@test.com", "name":"show name", "sub": "%s"}`, sub)), v) }) @@ -78,13 +79,14 @@ var _ = Describe("Test authentication service functions", func() { err = projectService.Init(context.TODO()) Expect(err).Should(BeNil()) - _, err = sysService.UpdateSystemInfo(context.TODO(), apisv1.SystemInfoRequest{ - LoginType: "local", - DexUserDefaultProjects: []model.ProjectRef{{ - Name: "default", - Roles: []string{"app-developer"}, - }}, - }) + info, err := sysService.Get(context.TODO()) + Expect(err).Should(BeNil()) + info.DexUserDefaultProjects = []model.ProjectRef{{ + Name: "default", + Roles: []string{"app-developer"}, + }} + info.DexUserDefaultPlatformRoles = []string{"admin"} + err = ds.Put(context.TODO(), info) Expect(err).Should(BeNil()) dexHandler := dexHandlerImpl{ @@ -96,9 +98,14 @@ var _ = Describe("Test authentication service functions", func() { resp, err := dexHandler.login(context.Background()) Expect(err).Should(BeNil()) Expect(resp.Email).Should(Equal("test@test.com")) - Expect(resp.Name).Should(Equal(sub)) + Expect(resp.Name).Should(Equal(strings.ToLower(sub))) Expect(resp.Alias).Should(Equal("show name")) + newUser, err := userService.GetUser(context.TODO(), resp.Name) + Expect(err).Should(BeNil()) + Expect(newUser.DexSub).Should(Equal(sub)) + Expect(newUser.UserRoles).Should(Equal([]string{"admin"})) + projects, err := projectService.ListUserProjects(context.TODO(), sub) Expect(err).Should(BeNil()) Expect(len(projects)).Should(Equal(1)) diff --git a/pkg/apiserver/domain/service/system_info.go b/pkg/apiserver/domain/service/system_info.go index f4c85faa0..45171d227 100644 --- a/pkg/apiserver/domain/service/system_info.go +++ b/pkg/apiserver/domain/service/system_info.go @@ -113,8 +113,9 @@ func (u systemInfoServiceImpl) UpdateSystemInfo(ctx context.Context, sysInfo v1. CreateTime: info.CreateTime, UpdateTime: time.Now(), }, - StatisticInfo: info.StatisticInfo, - DexUserDefaultProjects: sysInfo.DexUserDefaultProjects, + StatisticInfo: info.StatisticInfo, + DexUserDefaultProjects: sysInfo.DexUserDefaultProjects, + DexUserDefaultPlatformRoles: info.DexUserDefaultPlatformRoles, } if sysInfo.LoginType == model.LoginTypeDex { @@ -167,10 +168,11 @@ func (u systemInfoServiceImpl) Init(ctx context.Context) error { func convertInfoToBase(info *model.SystemInfo) v1.SystemInfo { return v1.SystemInfo{ - PlatformID: info.InstallID, - EnableCollection: info.EnableCollection, - LoginType: info.LoginType, - InstallTime: info.CreateTime, - DexUserDefaultProjects: info.DexUserDefaultProjects, + PlatformID: info.InstallID, + EnableCollection: info.EnableCollection, + LoginType: info.LoginType, + InstallTime: info.CreateTime, + DexUserDefaultProjects: info.DexUserDefaultProjects, + DexUserDefaultPlatformRoles: info.DexUserDefaultPlatformRoles, } } diff --git a/pkg/apiserver/interfaces/api/dto/v1/types.go b/pkg/apiserver/interfaces/api/dto/v1/types.go index 915ab1a70..b96470db2 100644 --- a/pkg/apiserver/interfaces/api/dto/v1/types.go +++ b/pkg/apiserver/interfaces/api/dto/v1/types.go @@ -1194,11 +1194,12 @@ type SystemInfoResponse struct { // SystemInfo system info type SystemInfo struct { - PlatformID string `json:"platformID"` - EnableCollection bool `json:"enableCollection"` - LoginType string `json:"loginType" validate:"oneof=dex local"` - InstallTime time.Time `json:"installTime,omitempty"` - DexUserDefaultProjects []model.ProjectRef `json:"dexUserDefaultProjects,omitempty"` + PlatformID string `json:"platformID"` + EnableCollection bool `json:"enableCollection"` + LoginType string `json:"loginType" validate:"oneof=dex local"` + InstallTime time.Time `json:"installTime,omitempty"` + DexUserDefaultProjects []model.ProjectRef `json:"dexUserDefaultProjects,omitempty"` + DexUserDefaultPlatformRoles []string `json:"dexUserDefaultPlatformRoles,omitempty"` } // StatisticInfo generated by cronJob running in backend diff --git a/pkg/multicluster/cluster_management.go b/pkg/multicluster/cluster_management.go index 1dbaeb0dd..a423022f3 100644 --- a/pkg/multicluster/cluster_management.go +++ b/pkg/multicluster/cluster_management.go @@ -20,6 +20,8 @@ import ( "bytes" "context" "fmt" + "strings" + "time" "github.com/briandowns/spinner" prismclusterv1alpha1 "github.com/kubevela/prism/pkg/apis/cluster/v1alpha1" @@ -89,9 +91,20 @@ func (clusterConfig *KubeClusterConfig) PostRegistration(ctx context.Context, cl if clusterConfig.CreateNamespace == "" { return nil } - if err := ensureNamespaceExists(ctx, cli, clusterConfig.ClusterName, clusterConfig.CreateNamespace); err != nil { - _ = DetachCluster(ctx, cli, clusterConfig.ClusterName, DetachClusterManagedClusterKubeConfigPathOption(clusterConfig.FilePath)) - return fmt.Errorf("failed to ensure %s namespace installed in cluster %s: %w", clusterConfig.CreateNamespace, clusterConfig.ClusterName, err) + // retry 3 times. + for i := 0; i < 3; i++ { + if err := ensureNamespaceExists(ctx, cli, clusterConfig.ClusterName, clusterConfig.CreateNamespace); err != nil { + // Cluster gateway discovers the cluster maybe be deferred, so we should retry. + if strings.Contains(err.Error(), "no such cluster") { + if i < 2 { + time.Sleep(time.Second * 1) + continue + } + } + _ = DetachCluster(ctx, cli, clusterConfig.ClusterName, DetachClusterManagedClusterKubeConfigPathOption(clusterConfig.FilePath)) + return fmt.Errorf("failed to ensure %s namespace installed in cluster %s: %w", clusterConfig.CreateNamespace, clusterConfig.ClusterName, err) + } + break } return nil } diff --git a/test/e2e-apiserver-test/suite_test.go b/test/e2e-apiserver-test/suite_test.go index 6581ef8d5..5ebdb5ba4 100644 --- a/test/e2e-apiserver-test/suite_test.go +++ b/test/e2e-apiserver-test/suite_test.go @@ -206,23 +206,23 @@ func delete(path string) *http.Response { } func decodeResponseBody(resp *http.Response, dst interface{}) error { - if resp.StatusCode != 200 { - return fmt.Errorf("response code is not 200: %d", resp.StatusCode) - } if resp.Body == nil { return fmt.Errorf("response body is nil") } defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } if dst != nil { - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return err - } err = json.Unmarshal(body, dst) if err != nil { return err } return nil } + if resp.StatusCode != 200 { + return fmt.Errorf("response code is not 200: %d body: %s", resp.StatusCode, string(body)) + } return nil }