Skip to content

Commit

Permalink
Improve update article (#9)
Browse files Browse the repository at this point in the history
* create and update article now call article.GetArticleBodySchemaFromResourceData

* add hasChange check for canonical_url and recreates listing if manually
deleted

* add a few more checks in data source article

* move GetListingBodySchemaFromResourceData and GetArticleBodySchemaFromResourceData
  • Loading branch information
karvounis authored Apr 16, 2022
1 parent 48c1b52 commit b7634be
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 123 deletions.
2 changes: 2 additions & 0 deletions docs/resources/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ resource "forem_article" "example_full" {
### Read-Only

- `comments_count` (Number) Number of comments.
- `created_at` (String) When the listing was created.
- `flare_tag` (Map of String) Flare tag object of the article.
- `id` (String) ID of the article.
- `organization` (Map of String) Organization object of the article.
Expand All @@ -107,6 +108,7 @@ resource "forem_article" "example_full" {
- `published_timestamp` (String) When the article was published.
- `reading_time_minutes` (Number) Article reading time in minutes.
- `slug` (String) Slug of the article.
- `updated_at` (String) When the listing was updated.
- `url` (String) Full article URL.
- `user` (Map of String) User object of the article.

Expand Down
17 changes: 17 additions & 0 deletions forem/data_source_article_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ func TestAccArticleDataSource_queryByID(t *testing.T) {
resource.TestCheckResourceAttrSet(resourceName, "body_markdown"),
resource.TestCheckResourceAttrSet(resourceName, "slug"),
resource.TestCheckResourceAttrSet(resourceName, "path"),
resource.TestCheckResourceAttrSet(resourceName, "created_at"),
resource.TestCheckNoResourceAttr(resourceName, "updated_at"),
resource.TestCheckResourceAttrSet(resourceName, "user.username"),
resource.TestCheckResourceAttrSet(resourceName, "published_at"),
resource.TestCheckResourceAttrSet(resourceName, "published_timestamp"),
resource.TestCheckResourceAttrSet(resourceName, "comments_count"),
resource.TestCheckResourceAttrSet(resourceName, "positive_reactions_count"),
resource.TestCheckResourceAttrSet(resourceName, "public_reactions_count"),
resource.TestCheckResourceAttrSet(resourceName, "reading_time_minutes"),
),
},
},
Expand All @@ -47,6 +56,14 @@ func TestAccArticleDataSource_queryByUsernameAndSlug(t *testing.T) {
resource.TestCheckResourceAttrSet(resourceName, "body_markdown"),
resource.TestCheckResourceAttr(resourceName, "slug", articleSlug),
resource.TestCheckResourceAttrSet(resourceName, "path"),
resource.TestCheckResourceAttrSet(resourceName, "created_at"),
resource.TestCheckResourceAttrSet(resourceName, "user.username"),
resource.TestCheckResourceAttrSet(resourceName, "published_at"),
resource.TestCheckResourceAttrSet(resourceName, "published_timestamp"),
resource.TestCheckResourceAttrSet(resourceName, "comments_count"),
resource.TestCheckResourceAttrSet(resourceName, "positive_reactions_count"),
resource.TestCheckResourceAttrSet(resourceName, "public_reactions_count"),
resource.TestCheckResourceAttrSet(resourceName, "reading_time_minutes"),
),
},
},
Expand Down
130 changes: 60 additions & 70 deletions forem/resource_article.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"strconv"
"time"

"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
Expand Down Expand Up @@ -162,6 +163,16 @@ func resourceArticle() *schema.Resource {
Type: schema.TypeString,
},
},
"created_at": {
Description: "When the listing was created.",
Type: schema.TypeString,
Computed: true,
},
"updated_at": {
Description: "When the listing was updated.",
Type: schema.TypeString,
Computed: true,
},
},
}
}
Expand All @@ -174,91 +185,36 @@ func resourceArticleDelete(ctx context.Context, d *schema.ResourceData, meta int
func resourceArticleCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*dev.Client)

title := d.Get("title").(string)
abc := getArticleBodySchemaFromResourceData(d)
tflog.Debug(ctx, fmt.Sprintf("Creating article with title: `%s`", abc.Article.Title))

var ab dev.ArticleBodySchema
ab.Article.Title = title
ab.Article.BodyMarkdown = d.Get("body_markdown").(string)

if v, ok := d.GetOk("published"); ok {
ab.Article.Published = v.(bool)
}
if v, ok := d.GetOk("series"); ok {
ab.Article.Series = v.(string)
}
if v, ok := d.GetOk("cover_image"); ok {
ab.Article.MainImage = v.(string)
}
if v, ok := d.GetOk("canonical_url"); ok {
ab.Article.CanonicalURL = v.(string)
}
if v, ok := d.GetOk("description"); ok {
ab.Article.Description = v.(string)
}
if v, ok := d.GetOk("tags"); ok {
tags := v.([]interface{})
tagsList := []string{}
for _, t := range tags {
tagsList = append(tagsList, t.(string))
}
ab.Article.Tags = tagsList
}
if v, ok := d.GetOk("organization_id"); ok {
ab.Article.OrganizationID = v.(int32)
}

tflog.Debug(ctx, fmt.Sprintf("Creating article with title `%s`", title))

resp, err := client.CreateArticle(ab, nil)
resp, err := client.CreateArticle(abc, nil)
if err != nil {
return diag.FromErr(err)
}
tflog.Debug(ctx, fmt.Sprintf("Created article ID: `%d`", resp.ID))

d.SetId(strconv.Itoa(int(resp.ID)))
d.Set("created_at", time.Now().Format(time.RFC3339))

return resourceArticleRead(ctx, d, meta)
}

func resourceArticleUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*dev.Client)

if d.HasChanges("title", "body_markdown", "published", "series", "cover_image", "description", "tags", "organization_id", "canonical_url") {
var ab dev.ArticleBodySchema
ab.Article.Title = d.Get("title").(string)
ab.Article.BodyMarkdown = d.Get("body_markdown").(string)
abc := getArticleBodySchemaFromResourceData(d)
if !d.HasChange("canonical_url") {
abc.Article.CanonicalURL = ""
}
tflog.Debug(ctx, fmt.Sprintf("Updating article with ID: %s", d.Id()))
if _, err := client.UpdateArticle(d.Id(), abc, nil); err != nil {
return diag.FromErr(err)
}
tflog.Debug(ctx, fmt.Sprintf("Updated listing with ID: %s", d.Id()))

if v, ok := d.GetOk("published"); ok {
ab.Article.Published = v.(bool)
}
if v, ok := d.GetOk("series"); ok {
ab.Article.Series = v.(string)
}
if v, ok := d.GetOk("cover_image"); ok {
ab.Article.MainImage = v.(string)
}
if v, ok := d.GetOk("description"); ok {
ab.Article.Description = v.(string)
}
if v, ok := d.GetOk("canonical_url"); ok {
ab.Article.CanonicalURL = v.(string)
}
if v, ok := d.GetOk("tags"); ok {
tags := []string{}
for _, t := range v.([]interface{}) {
tags = append(tags, t.(string))
}
ab.Article.Tags = tags
}
if v, ok := d.GetOk("organization_id"); ok {
ab.Article.OrganizationID = v.(int32)
}
d.Set("updated_at", time.Now().Format(time.RFC3339))

_, err := client.UpdateArticle(d.Id(), ab, nil)
if err != nil {
return diag.FromErr(err)
}
}
return resourceArticleRead(ctx, d, meta)
}

Expand All @@ -280,7 +236,8 @@ func resourceArticleRead(ctx context.Context, d *schema.ResourceData, meta inter
return diag.FromErr(err)
}
if len(articleResp) == 0 {
return diag.Errorf("no more articles")
tflog.Debug(ctx, "No more articles!")
return resourceArticleCreate(ctx, d, meta)
}

for _, v := range articleResp {
Expand Down Expand Up @@ -353,3 +310,36 @@ func resourceArticleRead(ctx context.Context, d *schema.ResourceData, meta inter

return nil
}

func getArticleBodySchemaFromResourceData(d *schema.ResourceData) dev.ArticleBodySchema {
var abc dev.ArticleBodySchema
abc.Article.Title = d.Get("title").(string)
abc.Article.BodyMarkdown = d.Get("body_markdown").(string)

if v, ok := d.GetOk("published"); ok {
abc.Article.Published = v.(bool)
}
if v, ok := d.GetOk("series"); ok {
abc.Article.Series = v.(string)
}
if v, ok := d.GetOk("cover_image"); ok {
abc.Article.MainImage = v.(string)
}
if v, ok := d.GetOk("canonical_url"); ok {
abc.Article.CanonicalURL = v.(string)
}
if v, ok := d.GetOk("description"); ok {
abc.Article.Description = v.(string)
}
if v, ok := d.GetOk("tags"); ok {
tags := []string{}
for _, t := range v.([]interface{}) {
tags = append(tags, t.(string))
}
abc.Article.Tags = tags
}
if v, ok := d.GetOk("organization_id"); ok {
abc.Article.OrganizationID = v.(int32)
}
return abc
}
56 changes: 43 additions & 13 deletions forem/resource_article_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/karvounis/dev-client-go"
)

func TestAccArticle_basic(t *testing.T) {
func TestAccArticle_createDraft(t *testing.T) {
gofakeit.Seed(time.Now().UnixNano())

resourceName := "forem_article.test"
Expand All @@ -33,40 +33,50 @@ func TestAccArticle_basic(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "published", "false"),
resource.TestCheckResourceAttr(resourceName, "tags.#", "0"),
resource.TestCheckResourceAttrSet(resourceName, "slug"),
resource.TestCheckResourceAttrSet(resourceName, "canonical_url"),
resource.TestCheckResourceAttrSet(resourceName, "path"),
resource.TestCheckNoResourceAttr(resourceName, "series"),
resource.TestCheckResourceAttrSet(resourceName, "created_at"),
resource.TestCheckNoResourceAttr(resourceName, "updated_at"),
resource.TestCheckResourceAttrSet(resourceName, "user.username"),
resource.TestCheckResourceAttr(resourceName, "published_at", ""),
resource.TestCheckResourceAttr(resourceName, "published_timestamp", ""),
resource.TestCheckResourceAttr(resourceName, "comments_count", strconv.Itoa(0)),
resource.TestCheckResourceAttr(resourceName, "positive_reactions_count", strconv.Itoa(0)),
resource.TestCheckResourceAttr(resourceName, "public_reactions_count", strconv.Itoa(0)),
resource.TestCheckResourceAttr(resourceName, "page_views_count", strconv.Itoa(0)),
resource.TestCheckResourceAttrSet(resourceName, "reading_time_minutes"),
),
},
},
})
}

func TestAccArticle_full(t *testing.T) {
func TestAccArticle_publishAndEdit(t *testing.T) {
gofakeit.Seed(time.Now().UnixNano())

title := gofakeit.HipsterSentence(5)
published := gofakeit.Bool()
canonicalURL := gofakeit.URL()
tags := []string{gofakeit.Word(), gofakeit.Word(), gofakeit.Word()}
tags := []string{strings.ToLower(gofakeit.Word()), strings.ToLower(gofakeit.Word()), strings.ToLower(gofakeit.Word())}
series := gofakeit.LoremIpsumSentence(3)
published := true

article := &dev.Article{
Title: title,
Title: gofakeit.HipsterSentence(5),
BodyMarkdown: gofakeit.HipsterParagraph(2, 5, 10, "\n"),
Published: published,
Description: gofakeit.LoremIpsumSentence(5),
CanonicalURL: canonicalURL,
Description: gofakeit.LoremIpsumSentence(3),
CanonicalURL: gofakeit.URL(),
CoverImage: gofakeit.URL(),
TagList: tags,
}

articleUpd := &dev.Article{
Title: title,
Title: gofakeit.HipsterSentence(5),
BodyMarkdown: gofakeit.HipsterParagraph(2, 5, 10, "\n"),
Published: published,
Description: gofakeit.LoremIpsumSentence(5),
CanonicalURL: canonicalURL,
Description: gofakeit.LoremIpsumSentence(3),
CanonicalURL: gofakeit.URL(),
CoverImage: gofakeit.URL(),
TagList: append(tags, gofakeit.Word()),
TagList: append(tags, strings.ToLower(gofakeit.Word())),
}

resourceName := "forem_article.test"
Expand All @@ -89,6 +99,16 @@ func TestAccArticle_full(t *testing.T) {
resource.TestCheckResourceAttrSet(resourceName, "slug"),
resource.TestCheckResourceAttrSet(resourceName, "path"),
resource.TestCheckResourceAttr(resourceName, "series", series),
resource.TestCheckResourceAttrSet(resourceName, "created_at"),
resource.TestCheckNoResourceAttr(resourceName, "updated_at"),
resource.TestCheckResourceAttrSet(resourceName, "user.username"),
resource.TestCheckResourceAttrSet(resourceName, "published_at"),
resource.TestCheckResourceAttrSet(resourceName, "published_timestamp"),
resource.TestCheckResourceAttr(resourceName, "comments_count", strconv.Itoa(0)),
resource.TestCheckResourceAttr(resourceName, "positive_reactions_count", strconv.Itoa(0)),
resource.TestCheckResourceAttr(resourceName, "public_reactions_count", strconv.Itoa(0)),
resource.TestCheckResourceAttr(resourceName, "page_views_count", strconv.Itoa(0)),
resource.TestCheckResourceAttrSet(resourceName, "reading_time_minutes"),
),
},
{
Expand All @@ -104,6 +124,16 @@ func TestAccArticle_full(t *testing.T) {
resource.TestCheckResourceAttrSet(resourceName, "slug"),
resource.TestCheckResourceAttrSet(resourceName, "path"),
resource.TestCheckResourceAttr(resourceName, "series", series),
resource.TestCheckResourceAttrSet(resourceName, "created_at"),
resource.TestCheckResourceAttrSet(resourceName, "updated_at"),
resource.TestCheckResourceAttrSet(resourceName, "user.username"),
resource.TestCheckResourceAttrSet(resourceName, "published_at"),
resource.TestCheckResourceAttrSet(resourceName, "published_timestamp"),
resource.TestCheckResourceAttr(resourceName, "comments_count", strconv.Itoa(0)),
resource.TestCheckResourceAttr(resourceName, "positive_reactions_count", strconv.Itoa(0)),
resource.TestCheckResourceAttr(resourceName, "public_reactions_count", strconv.Itoa(0)),
resource.TestCheckResourceAttr(resourceName, "page_views_count", strconv.Itoa(0)),
resource.TestCheckResourceAttrSet(resourceName, "reading_time_minutes"),
),
},
},
Expand Down
34 changes: 30 additions & 4 deletions forem/resource_listing.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"regexp"
"strconv"
"terraform-provider-forem/internal/listing"
"time"

"github.com/hashicorp/terraform-plugin-log/tflog"
Expand Down Expand Up @@ -151,8 +150,8 @@ func resourceListingDelete(ctx context.Context, d *schema.ResourceData, meta int
func resourceListingCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*dev.Client)

lbc := listing.GetListingBodySchemaFromResourceData(d)
tflog.Debug(ctx, fmt.Sprintf("Creating listing with title `%s` and category `%s`", lbc.Listing.Title, lbc.Listing.Category))
lbc := getListingBodySchemaFromResourceData(d)
tflog.Debug(ctx, fmt.Sprintf("Creating listing with title: `%s` and category: `%s`", lbc.Listing.Title, lbc.Listing.Category))
resp, err := client.CreateListing(lbc, nil)
if err != nil {
return diag.FromErr(err)
Expand All @@ -169,7 +168,7 @@ func resourceListingUpdate(ctx context.Context, d *schema.ResourceData, meta int
client := meta.(*dev.Client)

tflog.Debug(ctx, fmt.Sprintf("Updating listing with ID: %s", d.Id()))
lbc := listing.GetListingBodySchemaFromResourceData(d)
lbc := getListingBodySchemaFromResourceData(d)
if _, err := client.UpdateListing(d.Id(), lbc, nil); err != nil {
return diag.FromErr(err)
}
Expand Down Expand Up @@ -226,3 +225,30 @@ func resourceListingRead(ctx context.Context, d *schema.ResourceData, meta inter

return nil
}

func getListingBodySchemaFromResourceData(d *schema.ResourceData) dev.ListingBodySchema {
var lbc dev.ListingBodySchema
lbc.Listing.Title = d.Get("title").(string)
lbc.Listing.BodyMarkdown = d.Get("body_markdown").(string)
lbc.Listing.Category = dev.ListingCategory(d.Get("category").(string))
if v, ok := d.GetOk("expires_at"); ok {
lbc.Listing.ExpiresAt = v.(string)
}
if v, ok := d.GetOk("contact_via_connect"); ok {
lbc.Listing.ContactViaConnect = v.(bool)
}
if v, ok := d.GetOk("location"); ok {
lbc.Listing.Location = v.(string)
}
if v, ok := d.GetOk("action"); ok {
lbc.Listing.Action = dev.Action(v.(string))
}
if v, ok := d.GetOk("tags"); ok {
tags := []string{}
for _, t := range v.([]interface{}) {
tags = append(tags, t.(string))
}
lbc.Listing.Tags = tags
}
return lbc
}
Loading

0 comments on commit b7634be

Please sign in to comment.