2022-06-25 21:36:24 +00:00
|
|
|
package gitea
|
|
|
|
|
|
|
|
import (
|
2023-05-17 07:34:11 +00:00
|
|
|
"errors"
|
2022-06-25 21:36:24 +00:00
|
|
|
"fmt"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"code.gitea.io/sdk/gitea"
|
2022-08-06 14:21:18 +00:00
|
|
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
2022-06-25 21:36:24 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
TeamName string = "name"
|
|
|
|
TeamOrg string = "organisation"
|
|
|
|
TeamDescription string = "description"
|
|
|
|
TeamPermissions string = "permission"
|
|
|
|
TeamCreateRepoFlag string = "can_create_repos"
|
|
|
|
TeamIncludeAllReposFlag string = "include_all_repositories"
|
|
|
|
TeamUnits string = "units"
|
2022-06-25 22:18:20 +00:00
|
|
|
TeamMembers string = "members"
|
2023-05-15 03:22:29 +00:00
|
|
|
TeamRepositories string = "repositories"
|
2022-06-25 21:36:24 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func resourceTeamRead(d *schema.ResourceData, meta interface{}) (err error) {
|
|
|
|
client := meta.(*gitea.Client)
|
|
|
|
|
|
|
|
id, err := strconv.ParseInt(d.Id(), 10, 64)
|
|
|
|
|
|
|
|
var resp *gitea.Response
|
|
|
|
var team *gitea.Team
|
|
|
|
|
|
|
|
team, resp, err = client.GetTeam(id)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
if resp.StatusCode == 404 {
|
|
|
|
d.SetId("")
|
|
|
|
return nil
|
|
|
|
} else {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-17 08:27:17 +00:00
|
|
|
err = setTeamResourceData(team, d, meta)
|
2022-06-25 21:36:24 +00:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceTeamCreate(d *schema.ResourceData, meta interface{}) (err error) {
|
|
|
|
client := meta.(*gitea.Client)
|
|
|
|
|
|
|
|
var team *gitea.Team
|
|
|
|
var units []gitea.RepoUnitType
|
|
|
|
|
|
|
|
if strings.Contains(d.Get(TeamUnits).(string), "repo.code") {
|
|
|
|
units = append(units, gitea.RepoUnitCode)
|
|
|
|
}
|
|
|
|
if strings.Contains(d.Get(TeamUnits).(string), "repo.issues") {
|
|
|
|
units = append(units, gitea.RepoUnitIssues)
|
|
|
|
}
|
|
|
|
if strings.Contains(d.Get(TeamUnits).(string), "repo.ext_issues") {
|
|
|
|
units = append(units, gitea.RepoUnitExtIssues)
|
|
|
|
}
|
|
|
|
if strings.Contains(d.Get(TeamUnits).(string), "repo.wiki") {
|
|
|
|
units = append(units, gitea.RepoUnitWiki)
|
|
|
|
}
|
|
|
|
if strings.Contains(d.Get(TeamUnits).(string), "repo.pulls") {
|
|
|
|
units = append(units, gitea.RepoUnitPulls)
|
|
|
|
}
|
|
|
|
if strings.Contains(d.Get(TeamUnits).(string), "repo.releases") {
|
|
|
|
units = append(units, gitea.RepoUnitReleases)
|
|
|
|
}
|
|
|
|
if strings.Contains(d.Get(TeamUnits).(string), "repo.ext_wiki") {
|
|
|
|
units = append(units, gitea.RepoUnitExtWiki)
|
|
|
|
}
|
|
|
|
if strings.Contains(d.Get(TeamUnits).(string), "repo.projects") {
|
|
|
|
units = append(units, gitea.RepoUnitProjects)
|
|
|
|
}
|
|
|
|
|
2023-05-15 03:22:29 +00:00
|
|
|
includeAllRepos := d.Get(TeamIncludeAllReposFlag).(bool)
|
|
|
|
|
2022-06-25 21:36:24 +00:00
|
|
|
opts := gitea.CreateTeamOption{
|
|
|
|
Name: d.Get(TeamName).(string),
|
|
|
|
Description: d.Get(TeamDescription).(string),
|
|
|
|
Permission: gitea.AccessMode(d.Get(TeamPermissions).(string)),
|
|
|
|
CanCreateOrgRepo: d.Get(TeamCreateRepoFlag).(bool),
|
2023-05-15 03:22:29 +00:00
|
|
|
IncludesAllRepositories: includeAllRepos,
|
2022-06-25 21:36:24 +00:00
|
|
|
Units: units,
|
|
|
|
}
|
|
|
|
|
|
|
|
team, _, err = client.CreateTeam(d.Get(TeamOrg).(string), opts)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-06-25 22:18:20 +00:00
|
|
|
users := d.Get(TeamMembers).([]interface{})
|
|
|
|
|
|
|
|
for _, user := range users {
|
|
|
|
if user != "" {
|
|
|
|
_, err = client.AddTeamMember(team.ID, user.(string))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-15 03:22:29 +00:00
|
|
|
if !includeAllRepos {
|
|
|
|
err = setTeamRepositories(team, d, meta, false)
|
|
|
|
if err != nil {
|
2023-05-17 07:34:11 +00:00
|
|
|
return err
|
2023-05-15 03:22:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-17 08:27:17 +00:00
|
|
|
err = setTeamResourceData(team, d, meta)
|
2022-06-25 21:36:24 +00:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceTeamUpdate(d *schema.ResourceData, meta interface{}) (err error) {
|
|
|
|
client := meta.(*gitea.Client)
|
|
|
|
|
|
|
|
id, err := strconv.ParseInt(d.Id(), 10, 64)
|
|
|
|
|
|
|
|
var resp *gitea.Response
|
|
|
|
var team *gitea.Team
|
|
|
|
|
|
|
|
team, resp, err = client.GetTeam(id)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
if resp.StatusCode == 404 {
|
|
|
|
resourceTeamCreate(d, meta)
|
|
|
|
} else {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
description := d.Get(TeamDescription).(string)
|
|
|
|
canCreateRepo := d.Get(TeamCreateRepoFlag).(bool)
|
|
|
|
includeAllRepos := d.Get(TeamIncludeAllReposFlag).(bool)
|
|
|
|
|
|
|
|
var units []gitea.RepoUnitType
|
|
|
|
|
|
|
|
if strings.Contains(d.Get(TeamUnits).(string), "repo.code") {
|
|
|
|
units = append(units, gitea.RepoUnitCode)
|
|
|
|
}
|
|
|
|
if strings.Contains(d.Get(TeamUnits).(string), "repo.issues") {
|
|
|
|
units = append(units, gitea.RepoUnitIssues)
|
|
|
|
}
|
|
|
|
if strings.Contains(d.Get(TeamUnits).(string), "repo.ext_issues") {
|
|
|
|
units = append(units, gitea.RepoUnitExtIssues)
|
|
|
|
}
|
|
|
|
if strings.Contains(d.Get(TeamUnits).(string), "repo.wiki") {
|
|
|
|
units = append(units, gitea.RepoUnitWiki)
|
|
|
|
}
|
|
|
|
if strings.Contains(d.Get(TeamUnits).(string), "repo.pulls") {
|
|
|
|
units = append(units, gitea.RepoUnitPulls)
|
|
|
|
}
|
|
|
|
if strings.Contains(d.Get(TeamUnits).(string), "repo.releases") {
|
|
|
|
units = append(units, gitea.RepoUnitReleases)
|
|
|
|
}
|
|
|
|
if strings.Contains(d.Get(TeamUnits).(string), "repo.ext_wiki") {
|
|
|
|
units = append(units, gitea.RepoUnitExtWiki)
|
|
|
|
}
|
|
|
|
if strings.Contains(d.Get(TeamUnits).(string), "repo.projects") {
|
|
|
|
units = append(units, gitea.RepoUnitProjects)
|
|
|
|
}
|
|
|
|
|
|
|
|
opts := gitea.EditTeamOption{
|
|
|
|
Name: d.Get(TeamName).(string),
|
|
|
|
Description: &description,
|
|
|
|
Permission: gitea.AccessMode(d.Get(TeamPermissions).(string)),
|
|
|
|
CanCreateOrgRepo: &canCreateRepo,
|
|
|
|
IncludesAllRepositories: &includeAllRepos,
|
|
|
|
Units: units,
|
|
|
|
}
|
|
|
|
|
|
|
|
resp, err = client.EditTeam(id, opts)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-06-25 22:18:20 +00:00
|
|
|
users := d.Get(TeamMembers).([]interface{})
|
|
|
|
|
|
|
|
for _, user := range users {
|
|
|
|
if user != "" {
|
|
|
|
_, err = client.AddTeamMember(team.ID, user.(string))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-15 03:22:29 +00:00
|
|
|
if !includeAllRepos {
|
|
|
|
err = setTeamRepositories(team, d, meta, true)
|
|
|
|
if err != nil {
|
2023-05-17 07:34:11 +00:00
|
|
|
return err
|
2023-05-15 03:22:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-25 21:36:24 +00:00
|
|
|
team, _, _ = client.GetTeam(id)
|
|
|
|
|
2023-05-17 08:27:17 +00:00
|
|
|
err = setTeamResourceData(team, d, meta)
|
2022-06-25 21:36:24 +00:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceTeamDelete(d *schema.ResourceData, meta interface{}) (err error) {
|
|
|
|
client := meta.(*gitea.Client)
|
|
|
|
|
|
|
|
id, err := strconv.ParseInt(d.Id(), 10, 64)
|
|
|
|
|
|
|
|
var resp *gitea.Response
|
|
|
|
|
|
|
|
resp, err = client.DeleteTeam(id)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
if resp.StatusCode == 404 {
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-05-17 08:27:17 +00:00
|
|
|
func setTeamResourceData(team *gitea.Team, d *schema.ResourceData, meta interface{}) (err error) {
|
|
|
|
client := meta.(*gitea.Client)
|
|
|
|
if err := client.CheckServerVersionConstraint(">= 1.19.4"); err != nil {
|
|
|
|
d.Set(TeamOrg, d.Get(TeamOrg).(string))
|
|
|
|
} else {
|
|
|
|
d.Set(TeamOrg, team.Organization.UserName)
|
|
|
|
}
|
2022-06-25 21:36:24 +00:00
|
|
|
d.SetId(fmt.Sprintf("%d", team.ID))
|
|
|
|
d.Set(TeamCreateRepoFlag, team.CanCreateOrgRepo)
|
|
|
|
d.Set(TeamDescription, team.Description)
|
|
|
|
d.Set(TeamName, team.Name)
|
|
|
|
d.Set(TeamPermissions, string(team.Permission))
|
|
|
|
d.Set(TeamIncludeAllReposFlag, team.IncludesAllRepositories)
|
|
|
|
d.Set(TeamUnits, d.Get(TeamUnits).(string))
|
2022-06-25 22:18:20 +00:00
|
|
|
d.Set(TeamMembers, d.Get(TeamMembers))
|
2023-05-15 03:22:29 +00:00
|
|
|
d.Set(TeamRepositories, d.Get(TeamRepositories))
|
2022-06-25 21:36:24 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceGiteaTeam() *schema.Resource {
|
|
|
|
return &schema.Resource{
|
|
|
|
Read: resourceTeamRead,
|
|
|
|
Create: resourceTeamCreate,
|
|
|
|
Update: resourceTeamUpdate,
|
|
|
|
Delete: resourceTeamDelete,
|
|
|
|
Importer: &schema.ResourceImporter{
|
2023-05-15 13:17:32 +00:00
|
|
|
StateContext: schema.ImportStatePassthroughContext,
|
2022-06-25 21:36:24 +00:00
|
|
|
},
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
|
|
"name": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
ForceNew: true,
|
|
|
|
Description: "Name of the Team",
|
|
|
|
},
|
|
|
|
"organisation": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
ForceNew: true,
|
|
|
|
Description: "The organisation which this Team is part of.",
|
|
|
|
},
|
|
|
|
"description": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: false,
|
|
|
|
Optional: true,
|
|
|
|
Default: "",
|
|
|
|
Description: "Description of the Team",
|
|
|
|
},
|
|
|
|
"permission": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: false,
|
|
|
|
Optional: true,
|
|
|
|
Default: "",
|
|
|
|
Description: "Permissions associated with this Team\n" +
|
|
|
|
"Can be `none`, `read`, `write`, `admin` or `owner`",
|
|
|
|
},
|
|
|
|
"can_create_repos": {
|
|
|
|
Type: schema.TypeBool,
|
|
|
|
Required: false,
|
|
|
|
Optional: true,
|
|
|
|
Default: true,
|
|
|
|
Description: "Flag if the Teams members should be able to create Rpositories in the Organisation",
|
|
|
|
},
|
|
|
|
"include_all_repositories": {
|
|
|
|
Type: schema.TypeBool,
|
|
|
|
Required: false,
|
|
|
|
Optional: true,
|
|
|
|
Default: true,
|
|
|
|
Description: "Flag if the Teams members should have access to all Repositories in the Organisation",
|
|
|
|
},
|
|
|
|
"units": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: false,
|
|
|
|
Optional: true,
|
|
|
|
Default: "[repo.code, repo.issues, repo.ext_issues, repo.wiki, repo.pulls, repo.releases, repo.projects, repo.ext_wiki]",
|
|
|
|
Description: "List of types of Repositories that should be allowed to be created from Team members.\n" +
|
|
|
|
"Can be `repo.code`, `repo.issues`, `repo.ext_issues`, `repo.wiki`, `repo.pulls`, `repo.releases`, `repo.projects` and/or `repo.ext_wiki`",
|
|
|
|
},
|
2022-06-25 22:18:20 +00:00
|
|
|
"members": {
|
|
|
|
Type: schema.TypeList,
|
|
|
|
Elem: &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
},
|
|
|
|
Optional: true,
|
|
|
|
Required: false,
|
|
|
|
Computed: true,
|
|
|
|
Description: "List of Users that should be part of this team",
|
|
|
|
},
|
2023-05-15 03:22:29 +00:00
|
|
|
"repositories": {
|
|
|
|
Type: schema.TypeList,
|
|
|
|
Elem: &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
},
|
|
|
|
Optional: true,
|
|
|
|
Required: false,
|
|
|
|
Computed: true,
|
|
|
|
Description: "List of Repositories that should be part of this team",
|
|
|
|
},
|
2022-06-25 21:36:24 +00:00
|
|
|
},
|
|
|
|
Description: "`gitea_team` manages Team that are part of an organisation.",
|
|
|
|
}
|
|
|
|
}
|
2023-05-15 03:22:29 +00:00
|
|
|
|
|
|
|
func setTeamRepositories(team *gitea.Team, d *schema.ResourceData, meta interface{}, update bool) (err error) {
|
|
|
|
client := meta.(*gitea.Client)
|
|
|
|
|
|
|
|
org := d.Get(TeamOrg).(string)
|
|
|
|
|
|
|
|
repositories := make(map[string]bool)
|
|
|
|
for _, repo := range d.Get(TeamRepositories).([]interface{}) {
|
|
|
|
if repo != "" {
|
|
|
|
repositories[repo.(string)] = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if update {
|
|
|
|
page := 1
|
|
|
|
|
|
|
|
for {
|
|
|
|
var existingRepositories []*gitea.Repository
|
|
|
|
existingRepositories, _, err = client.ListTeamRepositories(team.ID, gitea.ListTeamRepositoriesOptions{
|
|
|
|
ListOptions: gitea.ListOptions{
|
|
|
|
Page: page,
|
|
|
|
PageSize: 50,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
if err != nil {
|
2023-05-17 07:34:11 +00:00
|
|
|
return errors.New(fmt.Sprintf("[ERROR] Error listeng team repositories: %s", err))
|
2023-05-15 03:22:29 +00:00
|
|
|
}
|
|
|
|
if len(existingRepositories) == 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, exr := range existingRepositories {
|
|
|
|
_, exists := repositories[exr.Name]
|
|
|
|
if exists {
|
|
|
|
repositories[exr.Name] = false
|
|
|
|
} else {
|
|
|
|
_, err = client.RemoveTeamRepository(team.ID, org, exr.Name)
|
|
|
|
if err != nil {
|
2023-05-17 07:34:11 +00:00
|
|
|
return errors.New(fmt.Sprintf("[ERROR] Error removing team repository %q: %s", exr.Name, err))
|
2023-05-15 03:22:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
page += 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for repo, flag := range repositories {
|
|
|
|
if flag {
|
|
|
|
_, err = client.AddTeamRepository(team.ID, org, repo)
|
|
|
|
if err != nil {
|
2023-05-17 07:34:11 +00:00
|
|
|
return errors.New(fmt.Sprintf("[ERROR] Error adding team repository %q: %s", repo, err))
|
2023-05-15 03:22:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|