From 31cdcf48b42e10de2d75a6d9a45d54f52fc5c3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Wysoki=C5=84ski?= Date: Sat, 2 Sep 2023 07:27:43 +0200 Subject: [PATCH] feat: add repository data source (#6) --- docs/data-sources/repository.md | 46 ++++++ docs/resources/repository.md | 2 +- .../woodpecker_repository/data-source.tf | 3 + .../woodpecker_repository/resource.tf | 2 +- internal/data_source_repository.go | 150 ++++++++++++++++++ internal/data_source_repository_test.go | 52 ++++++ internal/provider.go | 1 + 7 files changed, 254 insertions(+), 2 deletions(-) create mode 100644 docs/data-sources/repository.md create mode 100644 examples/data-sources/woodpecker_repository/data-source.tf create mode 100644 internal/data_source_repository.go create mode 100644 internal/data_source_repository_test.go diff --git a/docs/data-sources/repository.md b/docs/data-sources/repository.md new file mode 100644 index 0000000..64caf7e --- /dev/null +++ b/docs/data-sources/repository.md @@ -0,0 +1,46 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "woodpecker_repository Data Source - terraform-provider-woodpecker" +subcategory: "" +description: |- + Use this data source to retrieve information about a repository. +--- + +# woodpecker_repository (Data Source) + +Use this data source to retrieve information about a repository. + +## Example Usage + +```terraform +data "woodpecker_repository" "test_repo" { + full_name = "Kichiyaki/test-repo" +} +``` + + +## Schema + +### Required + +- `full_name` (String) the full name of the repository (format: owner/reponame) + +### Read-Only + +- `allow_pull_requests` (Boolean) Enables handling webhook's pull request event. If disabled, then pipeline won't run for pull requests. +- `avatar_url` (String) the repository's avatar URL +- `clone_url` (String) the URL to clone repository +- `config_file` (String) The path to the pipeline config file or folder. By default it is left empty which will use the following configuration resolution .woodpecker/*.yml -> .woodpecker/*.yaml -> .woodpecker.yml -> .woodpecker.yaml. +- `default_branch` (String) the name of the default branch +- `forge_remote_id` (String) the unique identifier for the repository on the forge +- `id` (Number) the repository's id +- `is_gated` (Boolean) when true, every pipeline needs to be approved before being executed +- `is_private` (Boolean) whether the repo (SCM) is private +- `is_trusted` (Boolean) when true, underlying pipeline containers get access to escalated capabilities like mounting volumes +- `name` (String) the name of the repository +- `netrc_only_trusted` (Boolean) whether netrc credentials should be only injected into trusted containers, see [the docs](https://woodpecker-ci.org/docs/usage/project-settings#only-inject-netrc-credentials-into-trusted-containers) for more info +- `owner` (String) the owner of the repository +- `scm` (String) type of repository (see [the source code](https://github.com/woodpecker-ci/woodpecker/blob/main/server/model/const.go#L67)) +- `timeout` (Number) after this timeout a pipeline has to finish or will be treated as timed out (in minutes) +- `url` (String) the URL of the repository on the forge +- `visibility` (String) project visibility (public, private, internal), see [the docs](https://woodpecker-ci.org/docs/usage/project-settings#project-visibility) for more info diff --git a/docs/resources/repository.md b/docs/resources/repository.md index e028f3f..273aa48 100644 --- a/docs/resources/repository.md +++ b/docs/resources/repository.md @@ -14,7 +14,7 @@ Provides a repository resource. ```terraform resource "woodpecker_repository" "test_repo" { - full_name = "%s" + full_name = "Kichiyaki/test-repo" is_trusted = true visibility = "public" } diff --git a/examples/data-sources/woodpecker_repository/data-source.tf b/examples/data-sources/woodpecker_repository/data-source.tf new file mode 100644 index 0000000..c102a12 --- /dev/null +++ b/examples/data-sources/woodpecker_repository/data-source.tf @@ -0,0 +1,3 @@ +data "woodpecker_repository" "test_repo" { + full_name = "Kichiyaki/test-repo" +} diff --git a/examples/resources/woodpecker_repository/resource.tf b/examples/resources/woodpecker_repository/resource.tf index 0680c6c..c17a3e1 100644 --- a/examples/resources/woodpecker_repository/resource.tf +++ b/examples/resources/woodpecker_repository/resource.tf @@ -1,5 +1,5 @@ resource "woodpecker_repository" "test_repo" { - full_name = "%s" + full_name = "Kichiyaki/test-repo" is_trusted = true visibility = "public" } diff --git a/internal/data_source_repository.go b/internal/data_source_repository.go new file mode 100644 index 0000000..a2e7802 --- /dev/null +++ b/internal/data_source_repository.go @@ -0,0 +1,150 @@ +package internal + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/woodpecker-ci/woodpecker/woodpecker-go/woodpecker" +) + +type repositoryDataSource struct { + client woodpecker.Client +} + +var _ datasource.DataSource = (*repositoryDataSource)(nil) +var _ datasource.DataSourceWithConfigure = (*repositoryDataSource)(nil) + +func newRepositoryDataSource() datasource.DataSource { + return &repositoryDataSource{} +} + +func (d *repositoryDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_repository" +} + +func (d *repositoryDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + MarkdownDescription: "Use this data source to retrieve information about a repository.", + Attributes: map[string]schema.Attribute{ + "id": schema.Int64Attribute{ + Computed: true, + Description: "the repository's id", + }, + "forge_remote_id": schema.StringAttribute{ + Computed: true, + Description: "the unique identifier for the repository on the forge", + }, + "owner": schema.StringAttribute{ + Computed: true, + Description: "the owner of the repository", + }, + "name": schema.StringAttribute{ + Computed: true, + Description: "the name of the repository", + }, + "full_name": schema.StringAttribute{ + Required: true, + Description: "the full name of the repository (format: owner/reponame)", + }, + "avatar_url": schema.StringAttribute{ + Computed: true, + Description: "the repository's avatar URL", + }, + "url": schema.StringAttribute{ + Computed: true, + Description: "the URL of the repository on the forge", + }, + "clone_url": schema.StringAttribute{ + Computed: true, + Description: "the URL to clone repository", + }, + "default_branch": schema.StringAttribute{ + Computed: true, + Description: "the name of the default branch", + }, + "scm": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "type of repository " + + "(see [the source code](https://github.com/woodpecker-ci/woodpecker/blob/main/server/model/const.go#L67))", + }, + "timeout": schema.Int64Attribute{ + Computed: true, + Description: "after this timeout a pipeline has to finish or will be treated as timed out (in minutes)", + }, + "visibility": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "project visibility (public, private, internal), " + + "see [the docs](https://woodpecker-ci.org/docs/usage/project-settings#project-visibility) for more info", + }, + "is_private": schema.BoolAttribute{ + Computed: true, + Description: "whether the repo (SCM) is private", + }, + "is_trusted": schema.BoolAttribute{ + Computed: true, + Description: "when true, underlying pipeline containers get access to escalated capabilities like mounting volumes", + }, + "is_gated": schema.BoolAttribute{ + Computed: true, + Description: "when true, every pipeline needs to be approved before being executed", + }, + "allow_pull_requests": schema.BoolAttribute{ + Computed: true, + Description: "Enables handling webhook's pull request event. If disabled, then pipeline won't run for pull requests.", + }, + "config_file": schema.StringAttribute{ + Computed: true, + Description: "The path to the pipeline config file or folder. " + + "By default it is left empty which will use the following configuration " + + "resolution .woodpecker/*.yml -> .woodpecker/*.yaml -> .woodpecker.yml -> .woodpecker.yaml.", + }, + "netrc_only_trusted": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "whether netrc credentials should be only injected into trusted containers, " + + "see [the docs](https://woodpecker-ci.org/docs/usage/project-settings#only-inject-netrc-credentials-into-trusted-containers) for more info", + }, + }, + } +} + +func (d *repositoryDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + + client, ok := req.ProviderData.(woodpecker.Client) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Data Source Configure Type", + fmt.Sprintf("Expected woodpecker.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + return + } + + d.client = client +} + +func (d *repositoryDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var data repositoryModel + + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + repo, err := d.client.RepoLookup(data.FullName.ValueString()) + if err != nil { + resp.Diagnostics.AddError("Couldn't read repository data", err.Error()) + return + } + + resp.Diagnostics.Append(data.setValues(ctx, repo)...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} diff --git a/internal/data_source_repository_test.go b/internal/data_source_repository_test.go new file mode 100644 index 0000000..668ef03 --- /dev/null +++ b/internal/data_source_repository_test.go @@ -0,0 +1,52 @@ +package internal_test + +import ( + "fmt" + "strconv" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestRepositoryDataSource(t *testing.T) { + t.Parallel() + + repo := createRepo(t) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(` +resource "woodpecker_repository" "test_repo" { + full_name = "%s" +} + +data "woodpecker_repository" "test_repo" { + full_name = woodpecker_repository.test_repo.full_name +} +`, repo.FullName), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrSet("data.woodpecker_repository.test_repo", "id"), + resource.TestCheckResourceAttr("data.woodpecker_repository.test_repo", "forge_remote_id", strconv.FormatInt(repo.ID, 10)), + resource.TestCheckResourceAttr("data.woodpecker_repository.test_repo", "name", repo.Name), + resource.TestCheckResourceAttr("data.woodpecker_repository.test_repo", "owner", repo.Owner.UserName), + resource.TestCheckResourceAttr("data.woodpecker_repository.test_repo", "full_name", repo.FullName), + resource.TestCheckResourceAttr("data.woodpecker_repository.test_repo", "url", repo.HTMLURL), + resource.TestCheckResourceAttr("data.woodpecker_repository.test_repo", "clone_url", repo.CloneURL), + resource.TestCheckResourceAttr("data.woodpecker_repository.test_repo", "default_branch", repo.DefaultBranch), + resource.TestCheckResourceAttr("data.woodpecker_repository.test_repo", "scm", "git"), + resource.TestCheckResourceAttrSet("data.woodpecker_repository.test_repo", "timeout"), + resource.TestCheckResourceAttr("data.woodpecker_repository.test_repo", "visibility", "public"), + resource.TestCheckResourceAttr("data.woodpecker_repository.test_repo", "is_private", strconv.FormatBool(repo.Private)), + resource.TestCheckResourceAttr("data.woodpecker_repository.test_repo", "is_trusted", "false"), + resource.TestCheckResourceAttr("data.woodpecker_repository.test_repo", "is_gated", "false"), + resource.TestCheckResourceAttr("data.woodpecker_repository.test_repo", "allow_pull_requests", "true"), + resource.TestCheckResourceAttr("data.woodpecker_repository.test_repo", "config_file", ""), + resource.TestCheckResourceAttr("data.woodpecker_repository.test_repo", "netrc_only_trusted", "true"), + ), + }, + }, + }) +} diff --git a/internal/provider.go b/internal/provider.go index 84b60f6..c40dd9c 100644 --- a/internal/provider.go +++ b/internal/provider.go @@ -56,6 +56,7 @@ func (p *woodpeckerProvider) DataSources(_ context.Context) []func() datasource. return []func() datasource.DataSource{ newUserDataSource, newSecretDataSource, + newRepositoryDataSource, } }