diff --git a/CHANGELOG.md b/CHANGELOG.md index b1e2af7..747a568 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,5 +8,6 @@ All notable changes to this project will be documented in this file. - Added provider configuration. - Added organizations data-source. +- Added repositories data-source. - Added teams data-source. - Added users data-source. diff --git a/docs/data-sources/repositories.md b/docs/data-sources/repositories.md new file mode 100644 index 0000000..66f953d --- /dev/null +++ b/docs/data-sources/repositories.md @@ -0,0 +1,247 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "forgejo_repositories Data Source - terraform-provider-forgejo" +subcategory: "" +description: |- + Use this data source to retrieve information about existing forgejo repositories. +--- + +# forgejo_repositories (Data Source) + +Use this data source to retrieve information about existing forgejo repositories. + +## Example Usage + +```terraform +data "forgejo_repositories" "example" {} +``` + + +## Schema + +### Read-Only + +- `elements` (Attributes List) The list of repositories. (see [below for nested schema](#nestedatt--elements)) + + +### Nested Schema for `elements` + +Read-Only: + +- `allow_fast_forward_only_merge` (Boolean) Whether fast forward only merges are allowed or not. +- `allow_merge_commits` (Boolean) Whether merge commits are allowed or not. +- `allow_rebase` (Boolean) Whether updating a pull request branch by rebase is allowed or not. +- `allow_rebase_explicit` (Boolean) Whether rebase then merge commits are allowed or not. +- `allow_rebase_update` (Boolean) Whether rebase then fast forward merges are allowed or not. +- `allow_squash_merge` (Boolean) Whether squash merge commits are allowed on this repository or not. +- `archived` (Boolean) Whether the repository is archived or not. +- `archived_at` (String) The datetime at which the repository was archived. +- `avatar_url` (String) The URL of the avatar for the repository. +- `clone_url` (String) The URL to clone the repository. +- `created_at` (String) The datetime at which the repository was created. +- `default_allow_maintainer_edit` (Boolean) Whether maintainers have edit permissions by default or not. +- `default_branch` (String) The name of the default branch. +- `default_delete_branch_after_merge` (Boolean) Whether pull request branches are deleted by default after a merge or not. +- `default_merge_style` (String) Name of the default merge style. +- `default_update_style` (String) Name of the default update style. +- `description` (String) A description string. +- `empty` (Boolean) Whether the repository is empty or not. +- `external_tracker` (Attributes) (see [below for nested schema](#nestedatt--elements--external_tracker)) +- `external_wiki` (Attributes) (see [below for nested schema](#nestedatt--elements--external_wiki)) +- `fork` (Boolean) Whether the repository is a fork or not. +- `forks_count` (Number) The number of times the repository has been forked. +- `full_name` (String) The full name of the repository. +- `globally_editable_wiki` (Boolean) Whether anyone can edit the wiki or not. +- `has_actions` (Boolean) Whether the actions unit is enabled or not. +- `has_issues` (Boolean) Whether the issues unit is enabled or not. +- `has_packages` (Boolean) Whether the packages unit is enabled or not. +- `has_projects` (Boolean) Whether the projects unit is enabled or not. +- `has_pull_requests` (Boolean) Whether the pull requests unit is enabled or not. +- `has_releases` (Boolean) Whether the releases unit is enabled or not. +- `has_wiki` (Boolean) Whether the wiki unit is enabled or not. +- `html_url` (String) The HTTP URL of the repository. +- `id` (Number) The identifier of the repository. +- `ignore_whitespace_conflicts` (Boolean) Whether whitespaces are ignored when detecting pull request conflicts or not. +- `internal` (Boolean) Whether this is an internal repository or not. +- `internal_tracker` (Attributes) (see [below for nested schema](#nestedatt--elements--internal_tracker)) +- `language` (String) The main programming language used in the repository. +- `languages_url` (String) The URL to the languages page. +- `link` (String) The link. +- `mirror` (Boolean) Whether the repository is a mirror or not. +- `mirror_interval` (String) The mirror time interval. +- `mirror_updated` (String) The datetime at which the mirror was last updated. +- `name` (String) The name of the repository. +- `object_format_name` (String) The name of the object format. +- `open_issues_count` (Number) The number of open issues. +- `open_pr_counter` (Number) The number of open pull requests. +- `original_url` (String) The original URL. +- `owner` (Attributes) (see [below for nested schema](#nestedatt--elements--owner)) +- `permissions` (Attributes) (see [below for nested schema](#nestedatt--elements--permissions)) +- `private` (Boolean) Whether the repository is private or not. +- `release_counter` (Number) The number of releases. +- `repo_transfer` (Attributes) (see [below for nested schema](#nestedatt--elements--repo_transfer)) +- `size` (Number) The size of the repository in KiB. +- `ssh_url` (String) The SSH URL. +- `stars_count` (Number) The number of stars. +- `template` (Boolean) Whether the repository is a template or not. +- `topics` (List of String) The list of topics. +- `updated_at` (String) The datetime at which the repository was last updated. +- `url` (String) The API URL. +- `watchers_count` (Number) The number of watchers. +- `website` (String) The website URL. +- `wiki_branch` (String) The name of the default branch of the wiki. + + +### Nested Schema for `elements.external_tracker` + +Read-Only: + +- `description` (String) A description string. +- `external_tracker_format` (String) External issue tracker URL Format. Use the placeholders {user}, {repo} and {index} for the username, repository name and issue index. +- `external_tracker_regexp_pattern` (String) Regular Expression Pattern. The first captured group will be used in place of {index}. +- `external_tracker_style` (String) External issue tracker Number Format. +- `external_tracker_url` (String) A URL. + + + +### Nested Schema for `elements.external_wiki` + +Read-Only: + +- `description` (String) A description string. +- `external_wiki_url` (String) A URL. + + + +### Nested Schema for `elements.internal_tracker` + +Read-Only: + +- `allow_only_contributors_to_track_time` (Boolean) Whether only contributors are allowed to track time on issues or not. +- `enable_issue_dependencies` (Boolean) Whether issue dependencies are enabled or not. +- `enable_time_tracker` (Boolean) Whether time tracking is enabled or not. + + + +### Nested Schema for `elements.owner` + +Read-Only: + +- `active` (Boolean) Whether the user is active or not. +- `avatar_url` (String) The user's avatar URL. +- `created` (String) The user's creation date and time. +- `description` (String) A description string. +- `email` (String) The user's email address. +- `followers_count` (Number) The number of followers. +- `following_count` (Number) The number of followings. +- `full_name` (String) The user's full name. +- `html_url` (String) The URL to this user's Forgejo profile page. +- `id` (Number) The identifier of the user. +- `is_admin` (Boolean) Whether the user is an admin or not. +- `language` (String) The user's chosen language. +- `last_login` (String) The user's last login date and time. +- `location` (String) The user's advertised location. +- `login` (String) The login of the user. +- `login_name` (String) The user's authentication sign-in name. +- `prohibit_login` (Boolean) Whether the user is allowed to log in or not. +- `pronouns` (String) The user's advertised pronouns. +- `restricted` (Boolean) Whether the user is restricted or not. +- `source_id` (Number) The identifier of the users authentication source. +- `starred_repos_count` (Number) The number of repositoties starred by the user. +- `visibility` (String) The user's visibility option: limited, private, public. +- `website` (String) The user's advertised website. + + + +### Nested Schema for `elements.permissions` + +Read-Only: + +- `admin` (Boolean) Admin permission. +- `pull` (Boolean) Pull permission. +- `push` (Boolean) Push permission. + + + +### Nested Schema for `elements.repo_transfer` + +Read-Only: + +- `description` (String) A description string. +- `doer` (Attributes) (see [below for nested schema](#nestedatt--elements--repo_transfer--doer)) +- `recipient` (Attributes) (see [below for nested schema](#nestedatt--elements--repo_transfer--recipient)) +- `teams` (Attributes List) The list of teams for an organization. (see [below for nested schema](#nestedatt--elements--repo_transfer--teams)) + + +### Nested Schema for `elements.repo_transfer.doer` + +Read-Only: + +- `active` (Boolean) Whether the user is active or not. +- `avatar_url` (String) The user's avatar URL. +- `created` (String) The user's creation date and time. +- `description` (String) A description string. +- `email` (String) The user's email address. +- `followers_count` (Number) The number of followers. +- `following_count` (Number) The number of followings. +- `full_name` (String) The user's full name. +- `html_url` (String) The URL to this user's Forgejo profile page. +- `id` (Number) The identifier of the user. +- `is_admin` (Boolean) Whether the user is an admin or not. +- `language` (String) The user's chosen language. +- `last_login` (String) The user's last login date and time. +- `location` (String) The user's advertised location. +- `login` (String) The login of the user. +- `login_name` (String) The user's authentication sign-in name. +- `prohibit_login` (Boolean) Whether the user is allowed to log in or not. +- `pronouns` (String) The user's advertised pronouns. +- `restricted` (Boolean) Whether the user is restricted or not. +- `source_id` (Number) The identifier of the users authentication source. +- `starred_repos_count` (Number) The number of repositoties starred by the user. +- `visibility` (String) The user's visibility option: limited, private, public. +- `website` (String) The user's advertised website. + + + +### Nested Schema for `elements.repo_transfer.recipient` + +Read-Only: + +- `active` (Boolean) Whether the user is active or not. +- `avatar_url` (String) The user's avatar URL. +- `created` (String) The user's creation date and time. +- `description` (String) A description string. +- `email` (String) The user's email address. +- `followers_count` (Number) The number of followers. +- `following_count` (Number) The number of followings. +- `full_name` (String) The user's full name. +- `html_url` (String) The URL to this user's Forgejo profile page. +- `id` (Number) The identifier of the user. +- `is_admin` (Boolean) Whether the user is an admin or not. +- `language` (String) The user's chosen language. +- `last_login` (String) The user's last login date and time. +- `location` (String) The user's advertised location. +- `login` (String) The login of the user. +- `login_name` (String) The user's authentication sign-in name. +- `prohibit_login` (Boolean) Whether the user is allowed to log in or not. +- `pronouns` (String) The user's advertised pronouns. +- `restricted` (Boolean) Whether the user is restricted or not. +- `source_id` (Number) The identifier of the users authentication source. +- `starred_repos_count` (Number) The number of repositoties starred by the user. +- `visibility` (String) The user's visibility option: limited, private, public. +- `website` (String) The user's advertised website. + + + +### Nested Schema for `elements.repo_transfer.teams` + +Read-Only: + +- `can_create_org_repo` (Boolean) Whether members of this team can create repositories that will belong to the organization. +- `description` (String) A description string. +- `id` (Number) The identifier of the team. +- `includes_all_repositories` (Boolean) Whether members of this team can access all the repositories that belong to the organization. +- `name` (String) The team's name are a part of. +- `permission` (String) The members' permission level on the organization. +- `units` (List of String) The list of units permissions. +- `units_map` (Map of String) The map of units permissions and their level. diff --git a/examples/data-sources/forgejo_repositories/data-source.tf b/examples/data-sources/forgejo_repositories/data-source.tf new file mode 100644 index 0000000..4072536 --- /dev/null +++ b/examples/data-sources/forgejo_repositories/data-source.tf @@ -0,0 +1 @@ +data "forgejo_repositories" "example" {} diff --git a/internal/client/permissions.go b/internal/client/permissions.go new file mode 100644 index 0000000..4d2b65b --- /dev/null +++ b/internal/client/permissions.go @@ -0,0 +1,7 @@ +package client + +type Permission struct { + Admin bool `json:"admin"` + Pull bool `json:"pull"` + Push bool `json:"push"` +} diff --git a/internal/client/repositories.go b/internal/client/repositories.go new file mode 100644 index 0000000..718f211 --- /dev/null +++ b/internal/client/repositories.go @@ -0,0 +1,122 @@ +package client + +import ( + "context" + "fmt" + "net/url" + "time" +) + +type RepositoryExternalTracker struct { + Description string `json:"description"` + Format string `json:"external_tracker_format"` + RegexpPattern string `json:"external_tracker_regexp_pattern"` + Style string `json:"external_tracker_style"` + Url string `json:"external_tracker_url"` +} + +type RepositoryExternalWiki struct { + Description string `json:"description"` + Url string `json:"external_wiki_url"` +} + +type RepositoryInternalTracker struct { + AllowOnlyContributorsToTrackTime bool `json:"allow_only_contributors_to_track_time"` + EnableIssueDependencies bool `json:"enable_issue_dependencies"` + EnableTimeTracker bool `json:"enable_time_tracker"` +} + +type RepositoryTransfer struct { + Description string `json:"description"` + Doer *User `json:"doer"` + Recipient *User `json:"recipient"` + Teams []Team `json:"teams"` +} + +type Repository struct { + AllowFastForwardOnlyMerge bool `json:"allow_fast_forward_only_merge"` + AllowMergeCommits bool `json:"allow_merge_commits"` + AllowRebase bool `json:"allow_rebase"` + AllowRebaseExplicit bool `json:"allow_rebase_explicit"` + AllowRebaseUpdate bool `json:"allow_rebase_update"` + AllowSquashMerge bool `json:"allow_squash_merge"` + ArchivedAt time.Time `json:"archived_at"` + Archived bool `json:"archived"` + AvatarUrl string `json:"avatar_url"` + CloneUrl string `json:"clone_url"` + CreatedAt time.Time `json:"created_at"` + DefaultAllowMaintainerEdit bool `json:"default_allow_maintainer_edit"` + DefaultBranch string `json:"default_branch"` + DefaultDeleteBranchAfterMerge bool `json:"default_delete_branch_after_merge"` + DefaultMergeStyle string `json:"default_merge_style"` + DefaultUpdateStyle string `json:"default_update_style"` + Description string `json:"description"` + Empty bool `json:"empty"` + ExternalTracker *RepositoryExternalTracker `json:"external_tracker"` + ExternalWiki *RepositoryExternalWiki `json:"external_wiki"` + Fork bool `json:"fork"` + ForksCount int64 `json:"forks_count"` + FullName string `json:"full_name"` + GloballyEditableWiki bool `json:"globally_editable_wiki"` + HasActions bool `json:"has_actions"` + HasIssues bool `json:"has_issues"` + HasPackages bool `json:"has_packages"` + HasProjects bool `json:"has_projects"` + HasPullRequests bool `json:"has_pull_requests"` + HasReleases bool `json:"has_releases"` + HasWiki bool `json:"has_wiki"` + HtmlUrl string `json:"html_url"` + Id int64 `json:"id"` + IgnoreWhitespaceConflicts bool `json:"ignore_whitespace_conflicts"` + Internal bool `json:"internal"` + InternalTracker *RepositoryInternalTracker `json:"internal_tracker"` + Language string `json:"language"` + LanguagesUrl string `json:"languages_url"` + Link string `json:"link"` + Mirror bool `json:"mirror"` + MirrorInterval string `json:"mirror_interval"` + MirrorUpdated time.Time `json:"mirror_updated"` + Name string `json:"name"` + ObjectFormatName string `json:"object_format_name"` + OpenIssuesCount int64 `json:"open_issues_count"` + OpenPrCounter int64 `json:"open_pr_counter"` + OriginalUrl string `json:"original_url"` + Owner *User `json:"owner"` + Parent *Repository `json:"parent"` + Permissions *Permission `json:"permissions"` + Private bool `json:"private"` + ReleaseCounter int64 `json:"release_counter"` + RepoTransfer *RepositoryTransfer `json:"repo_transfer"` + Size int64 `json:"size"` + SshUrl string `json:"ssh_url"` + StarsCount int64 `json:"stars_count"` + Template bool `json:"template"` + Topics []string `json:"topics"` + UpdatedAt time.Time `json:"updated_at"` + Url string `json:"url"` + WatchersCount int64 `json:"watchers_count"` + Website string `json:"website"` + WikiBranch string `json:"wiki_branch"` +} + +func (c *Client) RepositoriesList(ctx context.Context) ([]Repository, error) { + type Response struct { + Data []Repository `json:"data"` + Ok bool `json:"ok"` + } + var response Response + query := make(url.Values) + query.Set("limit", "50") + query.Set("page", "1") + uriRef := url.URL{ + Path: "api/v1/repos/search", + RawQuery: query.Encode(), + } + if err := c.Send(ctx, "GET", &uriRef, nil, &response); err != nil { + return nil, fmt.Errorf("failed to search repositories: %w", err) + } + if !response.Ok { + return response.Data, fmt.Errorf("got a non OK status when querying repos/search") + } + return response.Data, nil +} diff --git a/internal/provider/permissions.go b/internal/provider/permissions.go new file mode 100644 index 0000000..dd833bb --- /dev/null +++ b/internal/provider/permissions.go @@ -0,0 +1,27 @@ +package provider + +import ( + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +type PermissionDataSourceModel struct { + Admin types.Bool `tfsdk:"admin"` + Pull types.Bool `tfsdk:"pull"` + Push types.Bool `tfsdk:"push"` +} + +var permissionSchemaAttributes = map[string]schema.Attribute{ + "admin": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Admin permission.", + }, + "pull": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Pull permission.", + }, + "push": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Push permission.", + }, +} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 63e4b95..7ac274f 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -81,6 +81,7 @@ func (p *Provider) Resources(ctx context.Context) []func() resource.Resource { func (p *Provider) DataSources(ctx context.Context) []func() datasource.DataSource { return []func() datasource.DataSource{ NewOrganizationsDataSource, + NewRepositoriesDataSource, NewTeamsDataSource, NewUsersDataSource, } diff --git a/internal/provider/repositories_data_source.go b/internal/provider/repositories_data_source.go new file mode 100644 index 0000000..f1c6519 --- /dev/null +++ b/internal/provider/repositories_data_source.go @@ -0,0 +1,580 @@ +package provider + +import ( + "context" + "fmt" + + "git.adyxax.org/adyxax/terraform-provider-forgejo/internal/client" + "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +type RepositoriesDataSource struct { + client *client.Client +} + +var _ datasource.DataSource = &RepositoriesDataSource{} // Ensure provider defined types fully satisfy framework interfaces +func NewRepositoriesDataSource() datasource.DataSource { + return &RepositoriesDataSource{} +} + +type RepositoriesDataSourceModel struct { + Elements []RepositoryDataSourceModel `tfsdk:"elements"` +} +type RepositoryDataSourceModel struct { + AllowFastForwardOnlyMerge types.Bool `tfsdk:"allow_fast_forward_only_merge"` + AllowMergeCommits types.Bool `tfsdk:"allow_merge_commits"` + AllowRebase types.Bool `tfsdk:"allow_rebase"` + AllowRebaseExplicit types.Bool `tfsdk:"allow_rebase_explicit"` + AllowRebaseUpdate types.Bool `tfsdk:"allow_rebase_update"` + AllowSquashMerge types.Bool `tfsdk:"allow_squash_merge"` + ArchivedAt timetypes.RFC3339 `tfsdk:"archived_at"` + Archived types.Bool `tfsdk:"archived"` + AvatarUrl types.String `tfsdk:"avatar_url"` + CloneUrl types.String `tfsdk:"clone_url"` + CreatedAt timetypes.RFC3339 `tfsdk:"created_at"` + DefaultAllowMaintainerEdit types.Bool `tfsdk:"default_allow_maintainer_edit"` + DefaultBranch types.String `tfsdk:"default_branch"` + DefaultDeleteBranchAfterMerge types.Bool `tfsdk:"default_delete_branch_after_merge"` + DefaultMergeStyle types.String `tfsdk:"default_merge_style"` + DefaultUpdateStyle types.String `tfsdk:"default_update_style"` + Description types.String `tfsdk:"description"` + Empty types.Bool `tfsdk:"empty"` + ExternalTracker *RepositoryExternalTrackerDataSourceModel `tfsdk:"external_tracker"` + ExternalWiki *RepositoryExternalWikiDataSourceModel `tfsdk:"external_wiki"` + Fork types.Bool `tfsdk:"fork"` + ForksCount types.Int64 `tfsdk:"forks_count"` + FullName types.String `tfsdk:"full_name"` + GloballyEditableWiki types.Bool `tfsdk:"globally_editable_wiki"` + HasActions types.Bool `tfsdk:"has_actions"` + HasIssues types.Bool `tfsdk:"has_issues"` + HasPackages types.Bool `tfsdk:"has_packages"` + HasProjects types.Bool `tfsdk:"has_projects"` + HasPullRequests types.Bool `tfsdk:"has_pull_requests"` + HasReleases types.Bool `tfsdk:"has_releases"` + HasWiki types.Bool `tfsdk:"has_wiki"` + HtmlUrl types.String `tfsdk:"html_url"` + Id types.Int64 `tfsdk:"id"` + IgnoreWhitespaceConflicts types.Bool `tfsdk:"ignore_whitespace_conflicts"` + Internal types.Bool `tfsdk:"internal"` + InternalTracker *RepositoryInternalTrackerDataSourceModel `tfsdk:"internal_tracker"` + Language types.String `tfsdk:"language"` + LanguagesUrl types.String `tfsdk:"languages_url"` + Link types.String `tfsdk:"link"` + Mirror types.Bool `tfsdk:"mirror"` + MirrorInterval types.String `tfsdk:"mirror_interval"` + MirrorUpdated timetypes.RFC3339 `tfsdk:"mirror_updated"` + Name types.String `tfsdk:"name"` + ObjectFormatName types.String `tfsdk:"object_format_name"` + OpenIssuesCount types.Int64 `tfsdk:"open_issues_count"` + OpenPrCounter types.Int64 `tfsdk:"open_pr_counter"` + OriginalUrl types.String `tfsdk:"original_url"` + Owner *UserDataSourceModel `tfsdk:"owner"` + //terraform does not support recursive schema definitions + //Parent *RepositoryDataSourceModel `tfsdk:"parent"` + Permissions *PermissionDataSourceModel `tfsdk:"permissions"` + Private types.Bool `tfsdk:"private"` + ReleaseCounter types.Int64 `tfsdk:"release_counter"` + RepoTransfer *RepositoryTransferDataSourceModel `tfsdk:"repo_transfer"` + Size types.Int64 `tfsdk:"size"` + SshUrl types.String `tfsdk:"ssh_url"` + StarsCount types.Int64 `tfsdk:"stars_count"` + Template types.Bool `tfsdk:"template"` + Topics []types.String `tfsdk:"topics"` + UpdatedAt timetypes.RFC3339 `tfsdk:"updated_at"` + Url types.String `tfsdk:"url"` + WatchersCount types.Int64 `tfsdk:"watchers_count"` + Website types.String `tfsdk:"website"` + WikiBranch types.String `tfsdk:"wiki_branch"` +} + +type RepositoryExternalTrackerDataSourceModel struct { + Description types.String `tfsdk:"description"` + Format types.String `tfsdk:"external_tracker_format"` + RegexpPattern types.String `tfsdk:"external_tracker_regexp_pattern"` + Style types.String `tfsdk:"external_tracker_style"` + Url types.String `tfsdk:"external_tracker_url"` +} + +type RepositoryExternalWikiDataSourceModel struct { + Description types.String `tfsdk:"description"` + Url types.String `tfsdk:"external_wiki_url"` +} + +type RepositoryInternalTrackerDataSourceModel struct { + AllowOnlyContributorsToTrackTime types.Bool `tfsdk:"allow_only_contributors_to_track_time"` + EnableIssueDependencies types.Bool `tfsdk:"enable_issue_dependencies"` + EnableTimeTracker types.Bool `tfsdk:"enable_time_tracker"` +} + +type RepositoryTransferDataSourceModel struct { + Description types.String `tfsdk:"description"` + Doer *UserDataSourceModel `tfsdk:"doer"` + Recipient *UserDataSourceModel `tfsdk:"recipient"` + Teams []TeamDataSourceModel `tfsdk:"teams"` +} + +func (d *RepositoriesDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_repositories" +} + +func (d *RepositoriesDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "elements": schema.ListNestedAttribute{ + Computed: true, + MarkdownDescription: "The list of repositories.", + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "allow_fast_forward_only_merge": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether fast forward only merges are allowed or not.", + }, + "allow_merge_commits": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether merge commits are allowed or not.", + }, + "allow_rebase": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether updating a pull request branch by rebase is allowed or not.", + }, + "allow_rebase_explicit": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether rebase then merge commits are allowed or not.", + }, + "allow_rebase_update": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether rebase then fast forward merges are allowed or not.", + }, + "allow_squash_merge": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether squash merge commits are allowed on this repository or not.", + }, + "archived_at": schema.StringAttribute{ + Computed: true, + CustomType: timetypes.RFC3339Type{}, + MarkdownDescription: "The datetime at which the repository was archived.", + }, + "archived": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether the repository is archived or not.", + }, + "avatar_url": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The URL of the avatar for the repository.", + }, + "clone_url": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The URL to clone the repository.", + }, + "created_at": schema.StringAttribute{ + Computed: true, + CustomType: timetypes.RFC3339Type{}, + MarkdownDescription: "The datetime at which the repository was created.", + }, + "default_allow_maintainer_edit": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether maintainers have edit permissions by default or not.", + }, + "default_branch": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The name of the default branch.", + }, + "default_delete_branch_after_merge": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether pull request branches are deleted by default after a merge or not.", + }, + "default_merge_style": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "Name of the default merge style.", + }, + "default_update_style": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "Name of the default update style.", + }, + "description": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "A description string.", + }, + "empty": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether the repository is empty or not.", + }, + "external_tracker": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ + "description": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "A description string.", + }, + "external_tracker_format": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "External issue tracker URL Format. Use the placeholders {user}, {repo} and {index} for the username, repository name and issue index.", + }, + "external_tracker_regexp_pattern": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "Regular Expression Pattern. The first captured group will be used in place of {index}.", + }, + "external_tracker_style": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "External issue tracker Number Format.", + }, + "external_tracker_url": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "A URL.", + }, + }, + Computed: true, + }, + "external_wiki": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ + "description": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "A description string.", + }, + "external_wiki_url": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "A URL.", + }, + }, + Computed: true, + }, + "fork": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether the repository is a fork or not.", + }, + "forks_count": schema.Int64Attribute{ + Computed: true, + MarkdownDescription: "The number of times the repository has been forked.", + }, + "full_name": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The full name of the repository.", + }, + "globally_editable_wiki": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether anyone can edit the wiki or not.", + }, + "has_actions": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether the actions unit is enabled or not.", + }, + "has_issues": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether the issues unit is enabled or not.", + }, + "has_packages": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether the packages unit is enabled or not.", + }, + "has_projects": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether the projects unit is enabled or not.", + }, + "has_pull_requests": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether the pull requests unit is enabled or not.", + }, + "has_releases": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether the releases unit is enabled or not.", + }, + "has_wiki": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether the wiki unit is enabled or not.", + }, + "html_url": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The HTTP URL of the repository.", + }, + "id": schema.Int64Attribute{ + Computed: true, + MarkdownDescription: "The identifier of the repository.", + }, + "ignore_whitespace_conflicts": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether whitespaces are ignored when detecting pull request conflicts or not.", + }, + "internal": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether this is an internal repository or not.", + }, + "internal_tracker": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ + "allow_only_contributors_to_track_time": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether only contributors are allowed to track time on issues or not.", + }, + "enable_issue_dependencies": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether issue dependencies are enabled or not.", + }, + "enable_time_tracker": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether time tracking is enabled or not.", + }, + }, + Computed: true, + }, + "language": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The main programming language used in the repository.", + }, + "languages_url": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The URL to the languages page.", + }, + "link": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The link.", + }, + "mirror": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether the repository is a mirror or not.", + }, + "mirror_interval": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The mirror time interval.", + }, + "mirror_updated": schema.StringAttribute{ + Computed: true, + CustomType: timetypes.RFC3339Type{}, + MarkdownDescription: "The datetime at which the mirror was last updated.", + }, + "name": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The name of the repository.", + }, + "object_format_name": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The name of the object format.", + }, + "open_issues_count": schema.Int64Attribute{ + Computed: true, + MarkdownDescription: "The number of open issues.", + }, + "open_pr_counter": schema.Int64Attribute{ + Computed: true, + MarkdownDescription: "The number of open pull requests.", + }, + "original_url": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The original URL.", + }, + "owner": schema.SingleNestedAttribute{ + Attributes: userSchemaAttributes, + Computed: true, + }, + //"parent" + "permissions": schema.SingleNestedAttribute{ + Attributes: permissionSchemaAttributes, + Computed: true, + }, + "private": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether the repository is private or not.", + }, + "release_counter": schema.Int64Attribute{ + Computed: true, + MarkdownDescription: "The number of releases.", + }, + "repo_transfer": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ + "description": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "A description string.", + }, + "doer": schema.SingleNestedAttribute{ + Attributes: userSchemaAttributes, + Computed: true, + }, + "recipient": schema.SingleNestedAttribute{ + Attributes: userSchemaAttributes, + Computed: true, + }, + "teams": teamSchemaAttributes, + }, + Computed: true, + }, + "size": schema.Int64Attribute{ + Computed: true, + MarkdownDescription: "The size of the repository in KiB.", + }, + "ssh_url": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The SSH URL.", + }, + "stars_count": schema.Int64Attribute{ + Computed: true, + MarkdownDescription: "The number of stars.", + }, + "template": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether the repository is a template or not.", + }, + "topics": schema.ListAttribute{ + Computed: true, + ElementType: types.StringType, + MarkdownDescription: "The list of topics.", + }, + "updated_at": schema.StringAttribute{ + Computed: true, + CustomType: timetypes.RFC3339Type{}, + MarkdownDescription: "The datetime at which the repository was last updated.", + }, + "url": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The API URL.", + }, + "watchers_count": schema.Int64Attribute{ + Computed: true, + MarkdownDescription: "The number of watchers.", + }, + "website": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The website URL.", + }, + "wiki_branch": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The name of the default branch of the wiki.", + }, + }, + }, + }, + }, + MarkdownDescription: "Use this data source to retrieve information about existing forgejo repositories.", + } +} + +func (d *RepositoriesDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + d.client, _ = req.ProviderData.(*client.Client) +} + +func (d *RepositoriesDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var data RepositoriesDataSourceModel + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + repositories, err := d.client.RepositoriesList(ctx) + if err != nil { + resp.Diagnostics.AddError("ListRepositories", fmt.Sprintf("failed to list repositories: %s", err)) + return + } + repositoriesList := make([]RepositoryDataSourceModel, len(repositories)) + for i, repository := range repositories { + repositoriesList[i] = RepositoryDataSourceModel{ + AllowFastForwardOnlyMerge: types.BoolValue(repository.AllowFastForwardOnlyMerge), + AllowMergeCommits: types.BoolValue(repository.AllowMergeCommits), + AllowRebase: types.BoolValue(repository.AllowRebase), + AllowRebaseExplicit: types.BoolValue(repository.AllowRebaseExplicit), + AllowRebaseUpdate: types.BoolValue(repository.AllowRebaseUpdate), + AllowSquashMerge: types.BoolValue(repository.AllowSquashMerge), + ArchivedAt: timetypes.NewRFC3339TimeValue(repository.ArchivedAt), + Archived: types.BoolValue(repository.Archived), + AvatarUrl: types.StringValue(repository.AvatarUrl), + CloneUrl: types.StringValue(repository.CloneUrl), + CreatedAt: timetypes.NewRFC3339TimeValue(repository.CreatedAt), + DefaultAllowMaintainerEdit: types.BoolValue(repository.DefaultAllowMaintainerEdit), + DefaultBranch: types.StringValue(repository.DefaultBranch), + DefaultDeleteBranchAfterMerge: types.BoolValue(repository.DefaultDeleteBranchAfterMerge), + DefaultMergeStyle: types.StringValue(repository.DefaultMergeStyle), + DefaultUpdateStyle: types.StringValue(repository.DefaultUpdateStyle), + Description: types.StringValue(repository.Description), + Empty: types.BoolValue(repository.Empty), + ExternalTracker: nil, + ExternalWiki: nil, + Fork: types.BoolValue(repository.Fork), + ForksCount: types.Int64Value(repository.ForksCount), + FullName: types.StringValue(repository.FullName), + GloballyEditableWiki: types.BoolValue(repository.GloballyEditableWiki), + HasActions: types.BoolValue(repository.HasActions), + HasIssues: types.BoolValue(repository.HasIssues), + HasPackages: types.BoolValue(repository.HasPackages), + HasProjects: types.BoolValue(repository.HasProjects), + HasPullRequests: types.BoolValue(repository.HasPullRequests), + HasReleases: types.BoolValue(repository.HasReleases), + HasWiki: types.BoolValue(repository.HasWiki), + HtmlUrl: types.StringValue(repository.HtmlUrl), + Id: types.Int64Value(repository.Id), + IgnoreWhitespaceConflicts: types.BoolValue(repository.IgnoreWhitespaceConflicts), + Internal: types.BoolValue(repository.Internal), + InternalTracker: nil, + Language: types.StringValue(repository.Language), + LanguagesUrl: types.StringValue(repository.LanguagesUrl), + Link: types.StringValue(repository.Link), + Mirror: types.BoolValue(repository.Mirror), + MirrorInterval: types.StringValue(repository.MirrorInterval), + MirrorUpdated: timetypes.NewRFC3339TimeValue(repository.MirrorUpdated), + Name: types.StringValue(repository.Name), + ObjectFormatName: types.StringValue(repository.ObjectFormatName), + OpenIssuesCount: types.Int64Value(repository.OpenIssuesCount), + OpenPrCounter: types.Int64Value(repository.OpenPrCounter), + OriginalUrl: types.StringValue(repository.OriginalUrl), + Owner: nil, + Permissions: nil, + Private: types.BoolValue(repository.Private), + ReleaseCounter: types.Int64Value(repository.ReleaseCounter), + RepoTransfer: nil, + Size: types.Int64Value(repository.Size), + SshUrl: types.StringValue(repository.SshUrl), + StarsCount: types.Int64Value(repository.StarsCount), + Template: types.BoolValue(repository.Template), + Topics: make([]types.String, len(repository.Topics)), + UpdatedAt: timetypes.NewRFC3339TimeValue(repository.UpdatedAt), + Url: types.StringValue(repository.Url), + WatchersCount: types.Int64Value(repository.WatchersCount), + Website: types.StringValue(repository.Website), + WikiBranch: types.StringValue(repository.WikiBranch), + } + if repository.ExternalTracker != nil { + repositoriesList[i].ExternalTracker = &RepositoryExternalTrackerDataSourceModel{ + Description: types.StringValue(repository.ExternalTracker.Description), + Format: types.StringValue(repository.ExternalTracker.Format), + RegexpPattern: types.StringValue(repository.ExternalTracker.RegexpPattern), + Style: types.StringValue(repository.ExternalTracker.Style), + Url: types.StringValue(repository.ExternalTracker.Url), + } + } + if repository.ExternalWiki != nil { + repositoriesList[i].ExternalWiki = &RepositoryExternalWikiDataSourceModel{ + Description: types.StringValue(repository.ExternalTracker.Description), + Url: types.StringValue(repository.ExternalTracker.Url), + } + } + if repository.InternalTracker != nil { + repositoriesList[i].InternalTracker = &RepositoryInternalTrackerDataSourceModel{ + AllowOnlyContributorsToTrackTime: types.BoolValue(repository.InternalTracker.AllowOnlyContributorsToTrackTime), + EnableIssueDependencies: types.BoolValue(repository.InternalTracker.EnableIssueDependencies), + EnableTimeTracker: types.BoolValue(repository.InternalTracker.EnableTimeTracker), + } + } + if repository.Owner != nil { + repositoriesList[i].Owner = populateUserDataSourceModel(repository.Owner) + } + if repository.Permissions != nil { + repositoriesList[i].Permissions = &PermissionDataSourceModel{ + Admin: types.BoolValue(repository.Permissions.Admin), + Pull: types.BoolValue(repository.Permissions.Pull), + Push: types.BoolValue(repository.Permissions.Push), + } + } + if repository.RepoTransfer != nil { + repositoriesList[i].RepoTransfer = &RepositoryTransferDataSourceModel{ + Description: types.StringValue(repository.RepoTransfer.Description), + Doer: populateUserDataSourceModel(repository.RepoTransfer.Doer), + Recipient: populateUserDataSourceModel(repository.RepoTransfer.Recipient), + Teams: make([]TeamDataSourceModel, len(repository.RepoTransfer.Teams)), + } + for j, team := range repository.RepoTransfer.Teams { + repositoriesList[i].RepoTransfer.Teams[j] = *populateTeamDataSourceModel(&team) + } + } + for j, topic := range repository.Topics { + repositoriesList[i].Topics[j] = types.StringValue(topic) + } + } + data.Elements = repositoriesList + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} diff --git a/internal/provider/teams_data_source.go b/internal/provider/teams_data_source.go index 2ff6f2a..4ee8e53 100644 --- a/internal/provider/teams_data_source.go +++ b/internal/provider/teams_data_source.go @@ -42,51 +42,53 @@ func (d *TeamsDataSource) Metadata(ctx context.Context, req datasource.MetadataR resp.TypeName = req.ProviderTypeName + "_teams" } +var teamSchemaAttributes = schema.ListNestedAttribute{ + Computed: true, + MarkdownDescription: "The list of teams for an organization.", + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "can_create_org_repo": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether members of this team can create repositories that will belong to the organization.", + }, + "description": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "A description string.", + }, + "id": schema.Int64Attribute{ + Computed: true, + MarkdownDescription: "The identifier of the team.", + }, + "includes_all_repositories": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether members of this team can access all the repositories that belong to the organization.", + }, + "name": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The team's name are a part of.", + }, + "permission": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The members' permission level on the organization.", + }, + "units": schema.ListAttribute{ + Computed: true, + ElementType: types.StringType, + MarkdownDescription: "The list of units permissions.", + }, + "units_map": schema.MapAttribute{ + Computed: true, + ElementType: types.StringType, + MarkdownDescription: "The map of units permissions and their level.", + }, + }, + }, +} + func (d *TeamsDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { resp.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ - "elements": schema.ListNestedAttribute{ - Computed: true, - MarkdownDescription: "The list of teams for an organization.", - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "can_create_org_repo": schema.BoolAttribute{ - Computed: true, - MarkdownDescription: "Whether members of this team can create repositories that will belong to the organization.", - }, - "description": schema.StringAttribute{ - Computed: true, - MarkdownDescription: "A description string.", - }, - "id": schema.Int64Attribute{ - Computed: true, - MarkdownDescription: "The identifier of the team.", - }, - "includes_all_repositories": schema.BoolAttribute{ - Computed: true, - MarkdownDescription: "Whether members of this team can access all the repositories that belong to the organization.", - }, - "name": schema.StringAttribute{ - Computed: true, - MarkdownDescription: "The team's name are a part of.", - }, - "permission": schema.StringAttribute{ - Computed: true, - MarkdownDescription: "The members' permission level on the organization.", - }, - "units": schema.ListAttribute{ - Computed: true, - ElementType: types.StringType, - MarkdownDescription: "The list of units permissions.", - }, - "units_map": schema.MapAttribute{ - Computed: true, - ElementType: types.StringType, - MarkdownDescription: "The map of units permissions and their level.", - }, - }, - }, - }, + "elements": teamSchemaAttributes, "organization_name": schema.StringAttribute{ MarkdownDescription: "The name of the organization the teams are a part of.", Required: true, @@ -100,6 +102,19 @@ func (d *TeamsDataSource) Configure(ctx context.Context, req datasource.Configur d.client, _ = req.ProviderData.(*client.Client) } +func populateTeamDataSourceModel(team *client.Team) *TeamDataSourceModel { + return &TeamDataSourceModel{ + CanCreateOrgRepo: types.BoolValue(team.CanCreateOrgRepo), + Description: types.StringValue(team.Description), + Id: types.Int64Value(team.Id), + IncludesAllRepositories: types.BoolValue(team.IncludesAllRepositories), + Name: types.StringValue(team.Name), + Permission: types.StringValue(team.Permission), + Units: make([]types.String, len(team.Units)), + UnitsMap: make(map[string]types.String), + } +} + func (d *TeamsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { var data TeamsDataSourceModel resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) @@ -113,16 +128,7 @@ func (d *TeamsDataSource) Read(ctx context.Context, req datasource.ReadRequest, } teamsList := make([]TeamDataSourceModel, len(teams)) for i, team := range teams { - teamsList[i] = TeamDataSourceModel{ - CanCreateOrgRepo: types.BoolValue(team.CanCreateOrgRepo), - Description: types.StringValue(team.Description), - Id: types.Int64Value(team.Id), - IncludesAllRepositories: types.BoolValue(team.IncludesAllRepositories), - Name: types.StringValue(team.Name), - Permission: types.StringValue(team.Permission), - Units: make([]types.String, len(team.Units)), - UnitsMap: make(map[string]types.String), - } + teamsList[i] = *populateTeamDataSourceModel(&team) slices.Sort(team.Units) for j, unit := range team.Units { teamsList[i].Units[j] = types.StringValue(unit) diff --git a/internal/provider/users_data_source.go b/internal/provider/users_data_source.go index 1a6ffdf..948d4de 100644 --- a/internal/provider/users_data_source.go +++ b/internal/provider/users_data_source.go @@ -53,6 +53,103 @@ func (d *UsersDataSource) Metadata(ctx context.Context, req datasource.MetadataR resp.TypeName = req.ProviderTypeName + "_users" } +var userSchemaAttributes = map[string]schema.Attribute{ + "active": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether the user is active or not.", + }, + "avatar_url": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The user's avatar URL.", + }, + "created": schema.StringAttribute{ + Computed: true, + CustomType: timetypes.RFC3339Type{}, + MarkdownDescription: "The user's creation date and time.", + }, + "description": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "A description string.", + }, + "email": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The user's email address.", + }, + "followers_count": schema.Int64Attribute{ + Computed: true, + MarkdownDescription: "The number of followers.", + }, + "following_count": schema.Int64Attribute{ + Computed: true, + MarkdownDescription: "The number of followings.", + }, + "full_name": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The user's full name.", + }, + "html_url": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The URL to this user's Forgejo profile page.", + }, + "id": schema.Int64Attribute{ + Computed: true, + MarkdownDescription: "The identifier of the user.", + }, + "is_admin": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether the user is an admin or not.", + }, + "language": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The user's chosen language.", + }, + "last_login": schema.StringAttribute{ + Computed: true, + CustomType: timetypes.RFC3339Type{}, + MarkdownDescription: "The user's last login date and time.", + }, + "location": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The user's advertised location.", + }, + "login_name": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The user's authentication sign-in name.", + }, + "login": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The login of the user.", + }, + "prohibit_login": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether the user is allowed to log in or not.", + }, + "pronouns": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The user's advertised pronouns.", + }, + "restricted": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "Whether the user is restricted or not.", + }, + "source_id": schema.Int64Attribute{ + Computed: true, + MarkdownDescription: "The identifier of the users authentication source.", + }, + "starred_repos_count": schema.Int64Attribute{ + Computed: true, + MarkdownDescription: "The number of repositoties starred by the user.", + }, + "visibility": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The user's visibility option: limited, private, public.", + }, + "website": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The user's advertised website.", + }, +} + func (d *UsersDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { resp.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ @@ -60,102 +157,7 @@ func (d *UsersDataSource) Schema(ctx context.Context, req datasource.SchemaReque Computed: true, MarkdownDescription: "The list of users.", NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "active": schema.BoolAttribute{ - Computed: true, - MarkdownDescription: "Whether the user is active or not.", - }, - "avatar_url": schema.StringAttribute{ - Computed: true, - MarkdownDescription: "The user's avatar URL.", - }, - "created": schema.StringAttribute{ - Computed: true, - CustomType: timetypes.RFC3339Type{}, - MarkdownDescription: "The user's creation date and time.", - }, - "description": schema.StringAttribute{ - Computed: true, - MarkdownDescription: "A description string.", - }, - "email": schema.StringAttribute{ - Computed: true, - MarkdownDescription: "The user's email address.", - }, - "followers_count": schema.Int64Attribute{ - Computed: true, - MarkdownDescription: "The number of followers.", - }, - "following_count": schema.Int64Attribute{ - Computed: true, - MarkdownDescription: "The number of followings.", - }, - "full_name": schema.StringAttribute{ - Computed: true, - MarkdownDescription: "The user's full name.", - }, - "html_url": schema.StringAttribute{ - Computed: true, - MarkdownDescription: "The URL to this user's Forgejo profile page.", - }, - "id": schema.Int64Attribute{ - Computed: true, - MarkdownDescription: "The identifier of the user.", - }, - "is_admin": schema.BoolAttribute{ - Computed: true, - MarkdownDescription: "Whether the user is an admin or not.", - }, - "language": schema.StringAttribute{ - Computed: true, - MarkdownDescription: "The user's chosen language.", - }, - "last_login": schema.StringAttribute{ - Computed: true, - CustomType: timetypes.RFC3339Type{}, - MarkdownDescription: "The user's last login date and time.", - }, - "location": schema.StringAttribute{ - Computed: true, - MarkdownDescription: "The user's advertised location.", - }, - "login_name": schema.StringAttribute{ - Computed: true, - MarkdownDescription: "The user's authentication sign-in name.", - }, - "login": schema.StringAttribute{ - Computed: true, - MarkdownDescription: "The login of the user.", - }, - "prohibit_login": schema.BoolAttribute{ - Computed: true, - MarkdownDescription: "Whether the user is allowed to log in or not.", - }, - "pronouns": schema.StringAttribute{ - Computed: true, - MarkdownDescription: "The user's advertised pronouns.", - }, - "restricted": schema.BoolAttribute{ - Computed: true, - MarkdownDescription: "Whether the user is restricted or not.", - }, - "source_id": schema.Int64Attribute{ - Computed: true, - MarkdownDescription: "The identifier of the users authentication source.", - }, - "starred_repos_count": schema.Int64Attribute{ - Computed: true, - MarkdownDescription: "The number of repositoties starred by the user.", - }, - "visibility": schema.StringAttribute{ - Computed: true, - MarkdownDescription: "The user's visibility option: limited, private, public.", - }, - "website": schema.StringAttribute{ - Computed: true, - MarkdownDescription: "The user's advertised website.", - }, - }, + Attributes: userSchemaAttributes, }, }, }, @@ -167,6 +169,34 @@ func (d *UsersDataSource) Configure(ctx context.Context, req datasource.Configur d.client, _ = req.ProviderData.(*client.Client) } +func populateUserDataSourceModel(user *client.User) *UserDataSourceModel { + return &UserDataSourceModel{ + Active: types.BoolValue(user.Active), + AvatarUrl: types.StringValue(user.AvatarUrl), + Created: timetypes.NewRFC3339TimeValue(user.Created), + Description: types.StringValue(user.Description), + Email: types.StringValue(user.Email), + FollowerCount: types.Int64Value(user.FollowerCount), + FollowingCount: types.Int64Value(user.FollowingCount), + FullName: types.StringValue(user.FullName), + HtmlUrl: types.StringValue(user.HtmlUrl), + Id: types.Int64Value(user.Id), + IsAdmin: types.BoolValue(user.IsAdmin), + Language: types.StringValue(user.Language), + LastLogin: timetypes.NewRFC3339TimeValue(user.LastLogin), + Location: types.StringValue(user.Location), + LoginName: types.StringValue(user.LoginName), + Login: types.StringValue(user.Login), + ProhibitLogin: types.BoolValue(user.ProhibitLogin), + Pronouns: types.StringValue(user.Pronouns), + Restricted: types.BoolValue(user.Restricted), + SourceId: types.Int64Value(user.SourceId), + StarredRepoCount: types.Int64Value(user.StarredRepoCount), + Visibility: types.StringValue(user.Visibility), + Website: types.StringValue(user.Website), + } +} + func (d *UsersDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { var data UsersDataSourceModel resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) @@ -180,31 +210,7 @@ func (d *UsersDataSource) Read(ctx context.Context, req datasource.ReadRequest, } userList := make([]UserDataSourceModel, len(users)) for i, user := range users { - userList[i] = UserDataSourceModel{ - Active: types.BoolValue(user.Active), - AvatarUrl: types.StringValue(user.AvatarUrl), - Created: timetypes.NewRFC3339TimeValue(user.Created), - Description: types.StringValue(user.Description), - Email: types.StringValue(user.Email), - FollowerCount: types.Int64Value(user.FollowerCount), - FollowingCount: types.Int64Value(user.FollowingCount), - FullName: types.StringValue(user.FullName), - HtmlUrl: types.StringValue(user.HtmlUrl), - Id: types.Int64Value(user.Id), - IsAdmin: types.BoolValue(user.IsAdmin), - Language: types.StringValue(user.Language), - LastLogin: timetypes.NewRFC3339TimeValue(user.LastLogin), - Location: types.StringValue(user.Location), - LoginName: types.StringValue(user.LoginName), - Login: types.StringValue(user.Login), - ProhibitLogin: types.BoolValue(user.ProhibitLogin), - Pronouns: types.StringValue(user.Pronouns), - Restricted: types.BoolValue(user.Restricted), - SourceId: types.Int64Value(user.SourceId), - StarredRepoCount: types.Int64Value(user.StarredRepoCount), - Visibility: types.StringValue(user.Visibility), - Website: types.StringValue(user.Website), - } + userList[i] = *populateUserDataSourceModel(&user) } data.Elements = userList resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)