Browse Source

Projects and roles syncing are fully operational

Rufus Deponian 3 years ago
parent
commit
edb4c5ec2f
3 changed files with 186 additions and 40 deletions
  1. 73 24
      main.go
  2. 5 2
      project_and_roles_template.conf
  3. 108 14
      utils.go

+ 73 - 24
main.go

@@ -3,39 +3,25 @@ package main
 import (
 	"fmt"
 
-	"github.com/alyu/configparser"
 	"github.com/gophercloud/gophercloud/openstack/identity/v3/projects"
+	"github.com/gophercloud/gophercloud/openstack/identity/v3/roles"
 )
 
 func main() {
-	//osclient := initIdentityClient()
-
-	// allProjects := osclient.getProjectsMap(domainID)
-	// for _, project := range allProjects {
-	// 	fmt.Println(project)
-	// }
-	// allUnits := getCleanUnitsMap(osclient.config)
-	// for _, unit := range allUnits {
-	// 	fmt.Println(*unit.BriefName)
-	// }
-
-	config, err := configparser.Read("./project_and_roles.conf")
-	checkErr(err)
-	people := getPeople(config)
-	for _, person := range people {
-		fmt.Println(person.PersonId.Id)
-	}
+	osclient := initIdentityClient()
 
-	// fmt.Println("Syncing projects...")
-	// osclient.syncProjects()
+	fmt.Println("Syncing projects...")
+	osclient.syncProjects()
 	// fmt.Println("Deleting projects...")
 	// osclient.deleteAllProjects()
-	//fmt.Println("Syncing roles...")
-	//syncRoles()
+	fmt.Println("Syncing role assignments")
+	osclient.syncRoleAssignments()
+	// fmt.Println("Deleting role assignments")
+	// osclient.deleteAllRoleAssignments()
 }
 
 func (osclient OpenstackIdentityClient) syncProjects() {
-	allUnits := getCleanUnitsMap(osclient.config)
+	allUnits := getCleanUnitsPersNumberMap(osclient.config)
 	allProjects := osclient.getProjectsMap()
 
 	for persNumber, unit := range allUnits {
@@ -67,6 +53,69 @@ func (osclient OpenstackIdentityClient) deleteAllProjects() {
 	}
 }
 
-func syncRoles() {
+func (osclient OpenstackIdentityClient) syncRoleAssignments() {
+	openstackProjects := osclient.getProjectsMap()
+	openstackUsers := osclient.getOpenstackUsersMap()
+	units := getCleanUnitsCodeMap(osclient.config)
+	people := getPeopleMap(osclient.config)
+	roleList := getRoles(osclient.config)
+
+	for _, role := range roleList {
+		// Get project ID from unit code
+		unitCode := unitCodeToInt(role.Extra)
+		unit := units[unitCode]
+		// Check if unit doesn't exist in units map
+		if unit.Id == 0 {
+			continue
+		}
+		projectID := openstackProjects[*unit.PersNumber].ID
+
+		person := people[role.PersonId]
+		var userID string
+		for _, login := range person.Logins {
+			user := openstackUsers[login]
+			if user.ID != "" {
+				userID = user.ID
+				break
+			}
+		}
+		// Check if user doesn't exist in Openstack
+		if userID == "" {
+			continue
+		}
+
+		assignOpts := roles.AssignOpts{
+			UserID:    userID,
+			ProjectID: projectID,
+		}
+
+		assignmentResult := roles.Assign(osclient.client, osclient.userRoleID, assignOpts)
+		checkErr(assignmentResult.ExtractErr())
+		fmt.Printf("Role %s on project %s assigned to %s\n", osclient.userRoleID, projectID, userID)
+	}
+}
+
+func (osclient OpenstackIdentityClient) deleteAllRoleAssignments() {
+	listAssignmentsOpts := roles.ListAssignmentsOpts{
+		RoleID: osclient.userRoleID,
+	}
+
+	allPages, err := roles.ListAssignments(osclient.client, listAssignmentsOpts).AllPages()
+	checkErr(err)
 
+	allRoleAssignments, err := roles.ExtractRoleAssignments(allPages)
+	checkErr(err)
+
+	index := 1
+	amount := len(allRoleAssignments)
+	for _, roleAssignment := range allRoleAssignments {
+		unassignOpts := roles.UnassignOpts{
+			UserID:    roleAssignment.User.ID,
+			ProjectID: roleAssignment.Scope.Project.ID,
+		}
+		unassignmentResult := roles.Unassign(osclient.client, osclient.userRoleID, unassignOpts)
+		checkErr(unassignmentResult.ExtractErr())
+		fmt.Printf("[%v/%v] %s --- %s\n", index, amount, roleAssignment.User.ID, roleAssignment.Scope.Project.ID)
+		index++
+	}
 }

+ 5 - 2
project_and_roles_template.conf

@@ -7,11 +7,14 @@ api12_key = Your-API-Key-Here
 identity_endpoint = http://controller-IP-Here:5000/v3
 
 # Данные о пользователе, от лица которого будут выполняться запросы
-# Пользователь должен иметь роль администратора
-domain_name = mephi
+# Пользователь должен иметь роль облачного администратора
+domain_name = internal
 project_name = UserProjectName
 username = GeraltFromRivia
 password = Plotva
 
 # ID домена, в котором находятся синхронизируемые проекты
 projects_domain_id = domain-id
+
+# ID роли, которая будет предоставлена пользователям на проектах
+user_role_id = role-id

+ 108 - 14
utils.go

@@ -2,18 +2,22 @@ package main
 
 import (
 	"fmt"
+	"strconv"
 	"strings"
 	"unicode"
 
 	"devel.mephi.ru/dyokunev/go-sdapi/sdApi1"
 	"devel.mephi.ru/dyokunev/go-sdapi/sdApi11"
+	"devel.mephi.ru/dyokunev/go-sdapi/sdApi12"
 	"github.com/alyu/configparser"
 	"github.com/gophercloud/gophercloud"
 	"github.com/gophercloud/gophercloud/openstack"
 	"github.com/gophercloud/gophercloud/openstack/identity/v3/projects"
+	"github.com/gophercloud/gophercloud/openstack/identity/v3/users"
 
 	asuModels "devel.mephi.ru/dyokunev/go-asu-models"
 	api11Models "devel.mephi.ru/dyokunev/go-sd-models/api11"
+	api12Models "devel.mephi.ru/dyokunev/go-sd-models/api12"
 )
 
 // H E L P E R S
@@ -37,9 +41,10 @@ func capitalize(str string) string {
 // O P E N S T A C K   C L I E N T
 
 type OpenstackIdentityClient struct {
-	client   *gophercloud.ServiceClient
-	config   *configparser.Configuration
-	domainID string
+	client     *gophercloud.ServiceClient
+	config     *configparser.Configuration
+	domainID   string
+	userRoleID string
 }
 
 func initIdentityClient() OpenstackIdentityClient {
@@ -49,6 +54,7 @@ func initIdentityClient() OpenstackIdentityClient {
 	checkErr(err)
 
 	domainID := section.ValueOf("projects_domain_id")
+	userRoleID := section.ValueOf("user_role_id")
 
 	opts := gophercloud.AuthOptions{
 		IdentityEndpoint: section.ValueOf("identity_endpoint"),
@@ -67,14 +73,36 @@ func initIdentityClient() OpenstackIdentityClient {
 	checkErr(err)
 
 	osclient := OpenstackIdentityClient{
-		client:   client,
-		config:   config,
-		domainID: domainID,
+		client:     client,
+		config:     config,
+		domainID:   domainID,
+		userRoleID: userRoleID,
 	}
 
 	return osclient
 }
 
+func (osclient OpenstackIdentityClient) getProjects() []projects.Project {
+	listOpts := projects.ListOpts{
+		DomainID: osclient.domainID,
+		Enabled:  pointerFromBool(true),
+		IsDomain: pointerFromBool(false),
+	}
+
+	allPages, err := projects.List(osclient.client, listOpts).AllPages()
+	checkErr(err)
+
+	allProjects, err := projects.ExtractProjects(allPages)
+	checkErr(err)
+
+	return allProjects
+}
+
+func (osclient OpenstackIdentityClient) getProjectsMap() map[int]projects.Project {
+	allProjects := osclient.getProjects()
+	return projectsToMap(allProjects)
+}
+
 func projectsToMap(allProjects []projects.Project) map[int]projects.Project {
 	projectsMap := map[int]projects.Project{}
 
@@ -89,20 +117,34 @@ func projectsToMap(allProjects []projects.Project) map[int]projects.Project {
 	return projectsMap
 }
 
-func (osclient OpenstackIdentityClient) getProjectsMap() map[int]projects.Project {
-	listOpts := projects.ListOpts{
+func (osclient OpenstackIdentityClient) getOpenstackUsers() []users.User {
+	listOpts := users.ListOpts{
 		DomainID: osclient.domainID,
 		Enabled:  pointerFromBool(true),
-		IsDomain: pointerFromBool(false),
 	}
 
-	allPages, err := projects.List(osclient.client, listOpts).AllPages()
+	allPages, err := users.List(osclient.client, listOpts).AllPages()
 	checkErr(err)
 
-	allProjects, err := projects.ExtractProjects(allPages)
+	allUsers, err := users.ExtractUsers(allPages)
 	checkErr(err)
 
-	return projectsToMap(allProjects)
+	return allUsers
+}
+
+func (osclient OpenstackIdentityClient) getOpenstackUsersMap() map[string]users.User {
+	allUsers := osclient.getOpenstackUsers()
+	return openstackUsersToMap(allUsers)
+}
+
+func openstackUsersToMap(allUsers []users.User) map[string]users.User {
+	openstackUsersMap := map[string]users.User{}
+
+	for _, user := range allUsers {
+		openstackUsersMap[user.Name] = user
+	}
+
+	return openstackUsersMap
 }
 
 func makeUpdateOpts(unit asuModels.Unit, domainID string) projects.UpdateOpts {
@@ -148,8 +190,7 @@ func getAllUnits(config *configparser.Configuration) asuModels.Units {
 	return allUnits
 }
 
-// Map of persNumber to Unit
-func getCleanUnitsMap(config *configparser.Configuration) map[int]asuModels.Unit {
+func getCleanUnitsPersNumberMap(config *configparser.Configuration) map[int]asuModels.Unit {
 	allUnits := getAllUnits(config)
 	idToPersNum := map[int]int{}
 	cleanUnits := map[int]asuModels.Unit{}
@@ -186,6 +227,26 @@ func getCleanUnitsMap(config *configparser.Configuration) map[int]asuModels.Unit
 	return cleanUnits
 }
 
+func getCleanUnitsCodeMap(config *configparser.Configuration) map[int]asuModels.Unit {
+	units := getCleanUnitsPersNumberMap(config)
+
+	codeToUnitsMap := map[int]asuModels.Unit{}
+
+	for _, unit := range units {
+		codeToUnitsMap[unitCodeToInt(unit.Code)] = unit
+	}
+
+	return codeToUnitsMap
+}
+
+func unitCodeToInt(code string) int {
+	var numCode int
+	code = strings.Replace(code, " ", "", -1)
+	numCode, err := strconv.Atoi(code)
+	checkErr(err)
+	return numCode
+}
+
 func newestUnit(unit1 asuModels.Unit, unit2 asuModels.Unit) asuModels.Unit {
 	if unit1.CreateOrderDate != nil && unit2.CreateOrderDate != nil {
 		if unit1.CreateOrderDate.Unix() > unit2.CreateOrderDate.Unix() {
@@ -210,3 +271,36 @@ func getPeople(config *configparser.Configuration) api11Models.People {
 
 	return people
 }
+
+func getPeopleMap(config *configparser.Configuration) map[int]api11Models.Person {
+	people := getPeople(config)
+	return peopleToMap(people)
+}
+
+func peopleToMap(people api11Models.People) map[int]api11Models.Person {
+	peopleMap := map[int]api11Models.Person{}
+
+	for _, person := range people {
+		peopleMap[person.Id] = person
+	}
+
+	return peopleMap
+}
+
+// R O L E S
+
+func getRoles(config *configparser.Configuration) api12Models.Roles {
+	section, err := config.Section("sd.mephi.ru")
+	checkErr(err)
+
+	sdApi12.SetApiKey(section.ValueOf("api12_key"))
+
+	heads, err := sdApi12.GetRoles(api12Models.Role{ServiceName: "voip", RoleName: "head"})
+	checkErr(err)
+	openstack_users, err := sdApi12.GetRoles(api12Models.Role{ServiceName: "voip", RoleName: "openstack_user"})
+	checkErr(err)
+
+	roles := append(heads, openstack_users...)
+
+	return roles
+}