diff --git a/.github/workflows/mkdocs-gh-deploy.yml b/.github/workflows/mkdocs-gh-deploy.yml index b0960d9..0ce7d40 100644 --- a/.github/workflows/mkdocs-gh-deploy.yml +++ b/.github/workflows/mkdocs-gh-deploy.yml @@ -27,7 +27,7 @@ jobs: run: pip install -r requirements.txt - name: MkDocs env: - GH_PAT: ${{ secrets.GH_PAT }} + GH_PAT: ${{ secrets.GITHUB_TOKEN }} run: | git remote set-url origin https://x-access-token:${GH_PAT}@github.com/${GITHUB_REPOSITORY}.git mkdocs gh-deploy diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b1e08c9..63fcbf0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,18 +28,18 @@ jobs: name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.16 + go-version: 1.19 - name: Import GPG key id: import_gpg - uses: hashicorp/ghaction-import-gpg@v2.1.0 - env: + uses: crazy-max/ghaction-import-gpg@v5.0.0 + with: # These secrets will need to be configured for the repository: - GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} - PASSPHRASE: ${{ secrets.PASSPHRASE }} + gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.PASSPHRASE }} - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v2.7.0 + uses: goreleaser/goreleaser-action@v3 with: version: latest args: release --rm-dist diff --git a/README.md b/README.md index a1e894e..3ffe650 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,20 @@ -![](https://github.com/chesshacker/terraform-provider-confluence/workflows/Build%20and%20Test/badge.svg) +![](https://github.com/mesomorphic/terraform-provider-confluence/workflows/Build%20and%20Test/badge.svg) # Terraform Provider for Confluence -[User Documentation](https://chesshacker.github.io/terraform-provider-confluence/) +[User Documentation](https://mesomorphic.github.io/terraform-provider-confluence/) ## Requirements -- [Terraform](https://www.terraform.io/downloads.html) -- [Go](https://golang.org/doc/install) +- [Terraform](https://www.terraform.io/downloads.html) +- [Go](https://golang.org/doc/install) ## Build and install the provider Clone this repository, enter the provider directory, build and install the provider: ```sh -$ git clone https://github.com/chesshacker/terraform-provider-confluence.git +$ git clone https://github.com/mesomorphic/terraform-provider-confluence.git $ cd terraform-provider-confluence $ make install ``` diff --git a/VERSION b/VERSION index 0ea3a94..7dff5b8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.0 +0.2.1 \ No newline at end of file diff --git a/confluence/attachment.go b/confluence/attachment.go index f00413c..edbc794 100644 --- a/confluence/attachment.go +++ b/confluence/attachment.go @@ -37,7 +37,7 @@ func (c *Client) CreateAttachment(attachment *Attachment, data, pageId string) ( return nil, err } if len(response.Results) != 1 { - return nil, errors.New("Unexpected number of results returned when creating attachment") + return nil, errors.New("unexpected number of results returned when creating attachment") } return &response.Results[0], nil } @@ -50,7 +50,7 @@ func (c *Client) UpdateAttachment(attachment *Attachment, data, pageId string) ( return nil, err } if len(response.Results) != 1 { - return nil, errors.New("Unexpected number of results returned when updating attachment") + return nil, errors.New("unexpected number of results returned when updating attachment") } return &response.Results[0], nil } diff --git a/confluence/content.go b/confluence/content.go index 38e7c91..0c06439 100644 --- a/confluence/content.go +++ b/confluence/content.go @@ -14,7 +14,7 @@ type Content struct { Id string `json:"id,omitempty"` Type string `json:"type,omitempty"` Title string `json:"title,omitempty"` - Space *Space `json:"space,omitempty"` + Space *SpaceKey `json:"space,omitempty"` Version *Version `json:"version,omitempty"` Body *Body `json:"body,omitempty"` Links *ContentLinks `json:"_links,omitempty"` @@ -27,8 +27,8 @@ type ContentLinks struct { WebUI string `json:"webui,omitempty"` } -// Space is part of Content -type Space struct { +// SpaceKey is part of Content +type SpaceKey struct { Key string `json:"key,omitempty"` } diff --git a/confluence/provider.go b/confluence/provider.go index 5fd661f..e08946f 100644 --- a/confluence/provider.go +++ b/confluence/provider.go @@ -55,6 +55,7 @@ func Provider() *schema.Provider { ResourcesMap: map[string]*schema.Resource{ "confluence_content": resourceContent(), "confluence_attachment": resourceAttachment(), + "confluence_space": resourceSpace(), }, ConfigureFunc: providerConfigure, } diff --git a/confluence/resource_content.go b/confluence/resource_content.go index 70043a4..d62a3ef 100644 --- a/confluence/resource_content.go +++ b/confluence/resource_content.go @@ -103,7 +103,7 @@ func contentFromResourceData(d *schema.ResourceData) *Content { result := &Content{ Id: d.Id(), Type: d.Get("type").(string), - Space: &Space{ + Space: &SpaceKey{ Key: d.Get("space").(string), }, Body: &Body{ diff --git a/confluence/resource_space.go b/confluence/resource_space.go new file mode 100644 index 0000000..fd77bdf --- /dev/null +++ b/confluence/resource_space.go @@ -0,0 +1,105 @@ +package confluence + +import ( + "strconv" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func resourceSpace() *schema.Resource { + return &schema.Resource{ + Create: resourceSpaceCreate, + Read: resourceSpaceRead, + Update: resourceSpaceUpdate, + Delete: resourceSpaceDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Schema: map[string]*schema.Schema{ + "key": { + Type: schema.TypeString, + Required: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringLenBetween(0, 255), + }, + "url": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceSpaceCreate(d *schema.ResourceData, m interface{}) error { + client := m.(*Client) + contentRequest := spaceFromResourceData(d) + contentResponse, err := client.CreateSpace(contentRequest) + + if err != nil { + return err + } + d.SetId(strconv.Itoa(contentResponse.Id)) + return resourceSpaceRead(d, m) +} + +func resourceSpaceRead(d *schema.ResourceData, m interface{}) error { + client := m.(*Client) + contentResponse, err := client.GetSpace(d.Get("key").(string)) + if err != nil { + d.SetId("") + return err + } + return updateResourceDataFromSpace(d, contentResponse, client) +} + +func resourceSpaceUpdate(d *schema.ResourceData, m interface{}) error { + client := m.(*Client) + contentRequest := spaceFromResourceData(d) + _, err := client.UpdateSpace(contentRequest) + if err != nil { + d.SetId("") + return err + } + return resourceSpaceRead(d, m) +} + +func resourceSpaceDelete(d *schema.ResourceData, m interface{}) error { + client := m.(*Client) + err := client.DeleteSpace(d.Get("key").(string)) + if err != nil { + return err + } + // d.SetId("") is automatically called assuming delete returns no errors + return nil +} + +func spaceFromResourceData(d *schema.ResourceData) *Space { + id, _ := strconv.Atoi(d.Id()) + result := &Space{ + Id: id, + Key: d.Get("key").(string), + Name: d.Get("name").(string), + } + return result +} + +func updateResourceDataFromSpace(d *schema.ResourceData, space *Space, client *Client) error { + d.SetId(strconv.Itoa(space.Id)) + m := map[string]interface{}{ + "key": space.Key, + "name": space.Name, + "url": space.Links.Base + space.Links.WebUI, + } + for k, v := range m { + err := d.Set(k, v) + if err != nil { + return err + } + } + return nil +} diff --git a/confluence/space.go b/confluence/space.go new file mode 100644 index 0000000..1e1adb3 --- /dev/null +++ b/confluence/space.go @@ -0,0 +1,61 @@ +package confluence + +import ( + "fmt" + "strings" +) + +// Content is a primary resource in Confluence +type Space struct { + Id int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Key string `json:"key,omitempty"` + Links *SpaceLinks `json:"_links,omitempty"` +} + +// ContentLinks is part of Content +type SpaceLinks struct { + Base string `json:"base,omitempty"` + WebUI string `json:"webui,omitempty"` +} + +func (c *Client) CreateSpace(space *Space) (*Space, error) { + var response Space + if err := c.Post("/rest/api/space", space, &response); err != nil { + return nil, err + } + return &response, nil +} + +func (c *Client) GetSpace(id string) (*Space, error) { + var response Space + path := fmt.Sprintf("/rest/api/space/%s", id) + if err := c.Get(path, &response); err != nil { + return nil, err + } + + return &response, nil +} + +func (c *Client) UpdateSpace(space *Space) (*Space, error) { + var response Space + + path := fmt.Sprintf("/rest/api/space/%s", space.Key) + if err := c.Put(path, space, &response); err != nil { + return nil, err + } + return &response, nil +} + +func (c *Client) DeleteSpace(id string) error { + path := fmt.Sprintf("/rest/api/space/%s", id) + if err := c.Delete(path); err != nil { + if strings.HasPrefix(err.Error(), "202 ") { + //202 is the delete API success response + //Other APIs return 204. Because, reasons. + return nil + } + return err + } + return nil +} diff --git a/examples/space/main.tf b/examples/space/main.tf new file mode 100644 index 0000000..bacc923 --- /dev/null +++ b/examples/space/main.tf @@ -0,0 +1,33 @@ +provider "confluence" { + site = var.site + user = var.user + token = var.token +} +resource confluence_space "example" { + key = var.space + name = "Terraformed Space" +} +resource confluence_content "example" { + space = confluence_space.example.key + title = "Terraformed Page" + body = "Terraformed Content" +} + +variable "site" { + type = string +} + +variable "user" { + type = string +} + +variable "token" { + type = string +} + +variable "space" { + type = string +} +output "example" { + value = confluence_space.example +} diff --git a/go.mod b/go.mod index b6b88f2..5998004 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/chesshacker/terraform-provider-confluence +module github.com/mesomorphic/terraform-provider-confluence go 1.16 diff --git a/main.go b/main.go index ca04a49..3708b02 100644 --- a/main.go +++ b/main.go @@ -1,8 +1,8 @@ package main import ( - "github.com/chesshacker/terraform-provider-confluence/confluence" "github.com/hashicorp/terraform-plugin-sdk/v2/plugin" + "github.com/mesomorphic/terraform-provider-confluence/confluence" ) func main() { diff --git a/mkdocs.yml b/mkdocs.yml index 7eb0a59..26afad5 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,9 +1,10 @@ site_name: "Terraform Provider: Confluence" -site_url: https://chesshacker.github.io/terraform-provider-confluence/ -repo_url: https://github.com/chesshacker/terraform-provider-confluence +site_url: https://github.com/mesomorphic/terraform-provider-confluence +repo_url: https://github.com/mesomorphic/terraform-provider-confluence nav: - Getting Started: index.md - Resources: - confluence_attachment: resources/confluence_attachment.md - confluence_content: resources/confluence_content.md + - confluence_space: resources/confluence_space.md theme: readthedocs diff --git a/scripts/changelog-links.sh b/scripts/changelog-links.sh index 983fe81..c602e6c 100755 --- a/scripts/changelog-links.sh +++ b/scripts/changelog-links.sh @@ -24,7 +24,7 @@ else SED="sed -i.bak -r -e" fi -PROVIDER_URL="https:\/\/github.com\/chesshacker\/terraform-provider-confluence\/issues" +PROVIDER_URL="https:\/\/github.com\/mesomorphic\/terraform-provider-confluence\/issues" $SED "s/GH-([0-9]+)/\[#\1\]\($PROVIDER_URL\/\1\)/g" -e 's/\[\[#(.+)([0-9])\)]$/(\[#\1\2))/g' CHANGELOG.md diff --git a/terraform-registry-manifest.json b/terraform-registry-manifest.json new file mode 100644 index 0000000..625ab56 --- /dev/null +++ b/terraform-registry-manifest.json @@ -0,0 +1,6 @@ +{ + "version": 1, + "metadata": { + "protocol_versions": ["5.0"] + } +} \ No newline at end of file