diff --git a/docs/resources/repository_key.md b/docs/resources/repository_key.md new file mode 100644 index 0000000..8171b97 --- /dev/null +++ b/docs/resources/repository_key.md @@ -0,0 +1,54 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "gitea_repository_key Resource - terraform-provider-gitea" +subcategory: "" +description: |- + gitea_repository_key manages a deploy key for a single gitea_repository. + Every key needs a unique name and unique key, i.e. no key can be added twice to the same repo +--- + +# gitea_repository_key (Resource) + +`gitea_repository_key` manages a deploy key for a single gitea_repository. + +Every key needs a unique name and unique key, i.e. no key can be added twice to the same repo + +## Example Usage + +```terraform +resource "tls_private_key" "example" { + type = "RSA" + rsa_bits = 4096 +} + +resource "gitea_repository" "example" { + name = "example" + private = true +} + +resource "gitea_repository_key" "example" { + repository = gitea_repository.example.id + title = "Example Deploy Key" + read_only = true + key = tls_private_key.example.public_key_openssh +} +``` + + +## Schema + +### Required + +- `key` (String) Armored SSH key to add +- `repository` (Number) The ID of the repository where the deploy key belongs to +- `title` (String) Name of the deploy key + +### Optional + +- `read_only` (Boolean) Whether this key has read or read/write access + +### Read-Only + +- `id` (String) The ID of this resource. + + diff --git a/gitea/provider.go b/gitea/provider.go index b8c59d3..be7b500 100644 --- a/gitea/provider.go +++ b/gitea/provider.go @@ -75,14 +75,15 @@ func Provider() *schema.Provider { "gitea_org": resourceGiteaOrg(), // "gitea_team": resourceGiteaTeam(), // "gitea_repo": resourceGiteaRepo(), - "gitea_user": resourceGiteaUser(), - "gitea_oauth2_app": resourceGiteaOauthApp(), - "gitea_repository": resourceGiteaRepository(), - "gitea_fork": resourceGiteaFork(), - "gitea_public_key": resourceGiteaPublicKey(), - "gitea_team": resourceGiteaTeam(), - "gitea_git_hook": resourceGiteaGitHook(), - "gitea_token": resourceGiteaToken(), + "gitea_user": resourceGiteaUser(), + "gitea_oauth2_app": resourceGiteaOauthApp(), + "gitea_repository": resourceGiteaRepository(), + "gitea_fork": resourceGiteaFork(), + "gitea_public_key": resourceGiteaPublicKey(), + "gitea_team": resourceGiteaTeam(), + "gitea_git_hook": resourceGiteaGitHook(), + "gitea_token": resourceGiteaToken(), + "gitea_repository_key": resourceGiteaRepositoryKey(), }, ConfigureFunc: providerConfigure, diff --git a/gitea/resource_gitea_repository_key.go b/gitea/resource_gitea_repository_key.go new file mode 100644 index 0000000..e7482d0 --- /dev/null +++ b/gitea/resource_gitea_repository_key.go @@ -0,0 +1,169 @@ +package gitea + +import ( + "fmt" + "strconv" + "strings" + + "code.gitea.io/sdk/gitea" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +const ( + deployKeyRepoId string = "repository" + deployKeyName string = "title" + deployKeyKey string = "key" + deployKeyReadOnly string = "read_only" +) + +func resourceRepoKeyIdParts(d *schema.ResourceData) (bool, int64, int64, error) { + parts := strings.Split(d.Id(), "/") + if len(parts) != 2 { + return false, 0, 0, nil + } + + repoId, err := strconv.ParseInt(parts[0], 10, 64) + if err != nil { + return true, 0, 0, err + } + keyId, err := strconv.ParseInt(parts[1], 10, 64) + if err != nil { + return true, 0, 0, err + } + return true, repoId, keyId, err +} + +func resourceRepoKeyRead(d *schema.ResourceData, meta interface{}) (err error) { + client := meta.(*gitea.Client) + + hasId, repoId, keyId, err := resourceRepoKeyIdParts(d) + if err != nil { + return err + } + if !hasId { + d.SetId("") + return nil + } + + repo, resp, err := client.GetRepoByID(repoId) + if err != nil { + if resp.StatusCode == 404 { + d.SetId("") + return nil + } else { + return err + } + } + + key, resp, err := client.GetDeployKey(repo.Owner.UserName, repo.Name, keyId) + if err != nil { + if resp.StatusCode == 404 { + d.SetId("") + return nil + } else { + return err + } + } + + err = setRepoKeyResourceData(key, repoId, d) + + return +} + +func resourceRepoKeyCreate(d *schema.ResourceData, meta interface{}) (err error) { + client := meta.(*gitea.Client) + + repo, _, err := client.GetRepoByID(int64(d.Get(deployKeyRepoId).(int))) + + if err != nil { + return err + } + + dk, _, err := client.CreateDeployKey(repo.Owner.UserName, repo.Name, gitea.CreateKeyOption{ + Title: d.Get(deployKeyName).(string), + ReadOnly: d.Get(deployKeyReadOnly).(bool), + Key: d.Get(deployKeyKey).(string), + }) + + if err != nil { + return err + } + + setRepoKeyResourceData(dk, repo.ID, d) + return nil +} + +func respurceRepoKeyDelete(d *schema.ResourceData, meta interface{}) (err error) { + client := meta.(*gitea.Client) + + hasId, repoId, keyId, err := resourceRepoKeyIdParts(d) + if err != nil { + return err + } + if !hasId { + d.SetId("") + return nil + } + + repo, resp, err := client.GetRepoByID(repoId) + if err != nil { + if resp.StatusCode == 404 { + d.SetId("") + return nil + } + return err + } + + client.DeleteDeployKey(repo.Owner.UserName, repo.Name, keyId) + return nil +} + +func setRepoKeyResourceData(dk *gitea.DeployKey, repoId int64, d *schema.ResourceData) (err error) { + d.SetId(fmt.Sprintf("%d/%d", repoId, dk.ID)) + d.Set(deployKeyRepoId, repoId) + d.Set(deployKeyReadOnly, dk.ReadOnly) + d.Set(deployKeyKey, dk.Key) + d.Set(deployKeyName, dk.Title) + return +} + +func resourceGiteaRepositoryKey() *schema.Resource { + return &schema.Resource{ + Read: resourceRepoKeyRead, + Create: resourceRepoKeyCreate, + Delete: respurceRepoKeyDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + Schema: map[string]*schema.Schema{ + deployKeyRepoId: { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + Description: "The ID of the repository where the deploy key belongs to", + }, + deployKeyKey: { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Armored SSH key to add", + }, + deployKeyReadOnly: { + Type: schema.TypeBool, + Required: false, + Optional: true, + Default: true, + ForceNew: true, + Description: "Whether this key has read or read/write access", + }, + deployKeyName: { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Name of the deploy key", + }, + }, + Description: "`gitea_repository_key` manages a deploy key for a single gitea_repository.\n\n" + + "Every key needs a unique name and unique key, i.e. no key can be added twice to the same repo", + } +}