@@ -20,6 +20,7 @@ import (
2020 "context"
2121 "fmt"
2222 "net/url"
23+ "strconv"
2324 "strings"
2425
2526 "github.com/circlefin/terraform-provider-quicknode/api/quicknode"
@@ -74,6 +75,7 @@ type EndpointResourceModel struct {
7475 Url types.String `tfsdk:"url"`
7576 Id types.String `tfsdk:"id"`
7677 Security types.Object `tfsdk:"security"`
78+ Tags types.List `tfsdk:"tags"`
7779}
7880
7981type EndpointResourceSecurityToken struct {
@@ -151,6 +153,11 @@ func (r *EndpointResource) Schema(ctx context.Context, req resource.SchemaReques
151153 objectplanmodifier .UseStateForUnknown (),
152154 },
153155 },
156+ "tags" : schema.ListAttribute {
157+ ElementType : types .StringType ,
158+ Optional : true ,
159+ MarkdownDescription : "Tags to associate with the endpoint" ,
160+ },
154161 },
155162 }
156163}
@@ -236,7 +243,6 @@ func (r *EndpointResource) Create(ctx context.Context, req resource.CreateReques
236243 Network : data .Network .ValueStringPointer (),
237244 },
238245 )
239-
240246 if err != nil {
241247 resp .Diagnostics .AddError (
242248 fmt .Sprintf ("%s - Creating Endpoint" , utils .ClientErrorSummary ),
@@ -315,6 +321,36 @@ func (r *EndpointResource) Create(ctx context.Context, req resource.CreateReques
315321 }
316322 }
317323
324+ var tags []string
325+ data .Tags .ElementsAs (ctx , & tags , false )
326+ for _ , tag := range tags {
327+ tagResp , err := r .client .CreateTagWithResponse (
328+ ctx ,
329+ data .Id .ValueString (),
330+ quicknode.CreateTagJSONRequestBody {
331+ Label : & tag ,
332+ },
333+ )
334+ if err != nil {
335+ resp .Diagnostics .AddError (
336+ fmt .Sprintf ("%s - Creating Tag: %s" , utils .ClientErrorSummary , tag ),
337+ utils .BuildClientErrorMessage (err ),
338+ )
339+ return
340+ } else if tagResp .StatusCode () != 200 {
341+ m , err := utils .BuildRequestErrorMessage (tagResp .Status (), tagResp .Body )
342+ if err != nil {
343+ resp .Diagnostics .AddWarning (fmt .Sprintf ("%s - Creating Tag" , utils .InternalErrorSummary ), utils .BuildInternalErrorMessage (err ))
344+ }
345+
346+ resp .Diagnostics .AddError (
347+ fmt .Sprintf ("%s - Creating Tag: %s" , utils .RequestErrorSummary , tag ),
348+ m ,
349+ )
350+ return
351+ }
352+ }
353+
318354 tflog .Trace (ctx , "created a resource" )
319355 // Save data into Terraform state
320356 resp .Diagnostics .Append (resp .State .Set (ctx , & data )... )
@@ -334,7 +370,6 @@ func (r *EndpointResource) Read(ctx context.Context, req resource.ReadRequest, r
334370 ctx ,
335371 data .Id .ValueString (),
336372 )
337-
338373 if err != nil {
339374 resp .Diagnostics .AddError (
340375 fmt .Sprintf ("%s - Reading Endpoint" , utils .ClientErrorSummary ),
@@ -389,6 +424,19 @@ func (r *EndpointResource) Read(ctx context.Context, req resource.ReadRequest, r
389424 data .Security = securityValueObject
390425 }
391426
427+ data .Tags = types .ListNull (types .StringType )
428+ if endpoint .Tags != nil && len (* endpoint .Tags ) > 0 {
429+ var tags []string
430+ for _ , tag := range * endpoint .Tags {
431+ if tag .Label != nil {
432+ tags = append (tags , * tag .Label )
433+ }
434+ }
435+ t , diags := types .ListValueFrom (ctx , types .StringType , tags )
436+ resp .Diagnostics .Append (diags ... )
437+ data .Tags = t
438+ }
439+
392440 // Save updated data into Terraform state
393441 resp .Diagnostics .Append (resp .State .Set (ctx , & data )... )
394442}
@@ -412,7 +460,6 @@ func (r *EndpointResource) Update(ctx context.Context, req resource.UpdateReques
412460 Label : & l ,
413461 },
414462 )
415-
416463 if err != nil {
417464 resp .Diagnostics .AddError (
418465 fmt .Sprintf ("%s - Patching Endpoint" , utils .ClientErrorSummary ),
@@ -434,6 +481,108 @@ func (r *EndpointResource) Update(ctx context.Context, req resource.UpdateReques
434481 return
435482 }
436483
484+ // Fetch current endpoint state to get tag IDs
485+ currentEndpointResp , err := r .client .ShowEndpointWithResponse (ctx , data .Id .ValueString ())
486+ if err != nil {
487+ resp .Diagnostics .AddError (
488+ fmt .Sprintf ("%s - Reading Endpoint for Tags" , utils .ClientErrorSummary ),
489+ utils .BuildClientErrorMessage (err ),
490+ )
491+ return
492+ }
493+ if currentEndpointResp .StatusCode () != 200 {
494+ m , err := utils .BuildRequestErrorMessage (currentEndpointResp .Status (), currentEndpointResp .Body )
495+ if err != nil {
496+ resp .Diagnostics .AddWarning (fmt .Sprintf ("%s - Reading Endpoint for Tags" , utils .InternalErrorSummary ), utils .BuildInternalErrorMessage (err ))
497+ }
498+ resp .Diagnostics .AddError (
499+ fmt .Sprintf ("%s - Reading Endpoint for Tags" , utils .RequestErrorSummary ),
500+ m ,
501+ )
502+ return
503+ }
504+
505+ currentTags := make (map [string ]int )
506+ if currentEndpointResp .JSON200 .Data .Tags != nil {
507+ for _ , tag := range * currentEndpointResp .JSON200 .Data .Tags {
508+ if tag .Label != nil && tag .TagId != nil {
509+ currentTags [* tag .Label ] = * tag .TagId
510+ }
511+ }
512+ }
513+
514+ var planTags []string
515+ resp .Diagnostics .Append (data .Tags .ElementsAs (ctx , & planTags , false )... )
516+ if resp .Diagnostics .HasError () {
517+ return
518+ }
519+
520+ // Create map of plan tags for easy lookup
521+ planTagsMap := make (map [string ]bool )
522+ for _ , tag := range planTags {
523+ planTagsMap [tag ] = true
524+ }
525+
526+ // Add new tags
527+ for _ , tag := range planTags {
528+ if _ , exists := currentTags [tag ]; ! exists {
529+ tagResp , err := r .client .CreateTagWithResponse (
530+ ctx ,
531+ data .Id .ValueString (),
532+ quicknode.CreateTagJSONRequestBody {
533+ Label : & tag ,
534+ },
535+ )
536+ if err != nil {
537+ resp .Diagnostics .AddError (
538+ fmt .Sprintf ("%s - Creating Tag" , utils .ClientErrorSummary ),
539+ utils .BuildClientErrorMessage (err ),
540+ )
541+ return
542+ }
543+ if tagResp .StatusCode () != 200 {
544+ m , err := utils .BuildRequestErrorMessage (tagResp .Status (), tagResp .Body )
545+ if err != nil {
546+ resp .Diagnostics .AddWarning (fmt .Sprintf ("%s - Creating Tag" , utils .InternalErrorSummary ), utils .BuildInternalErrorMessage (err ))
547+ }
548+ resp .Diagnostics .AddError (
549+ fmt .Sprintf ("%s - Creating Tag" , utils .RequestErrorSummary ),
550+ m ,
551+ )
552+ return
553+ }
554+ }
555+ }
556+
557+ // Remove deleted tags
558+ for label , id := range currentTags {
559+ if _ , exists := planTagsMap [label ]; ! exists {
560+ delResp , err := r .client .DeleteTagWithResponse (
561+ ctx ,
562+ data .Id .ValueString (),
563+ strconv .Itoa (id ),
564+ )
565+ if err != nil {
566+ resp .Diagnostics .AddError (
567+ fmt .Sprintf ("%s - Deleting Tag" , utils .ClientErrorSummary ),
568+ utils .BuildClientErrorMessage (err ),
569+ )
570+ return
571+ }
572+ if delResp .StatusCode () != 200 {
573+ m , err := utils .BuildRequestErrorMessage (delResp .Status (), delResp .Body )
574+ if err != nil {
575+ resp .Diagnostics .AddWarning (fmt .Sprintf ("%s - Deleting Tag" , utils .InternalErrorSummary ), utils .BuildInternalErrorMessage (err ))
576+ }
577+ resp .Diagnostics .AddError (
578+ fmt .Sprintf ("%s - Deleting Tag" , utils .RequestErrorSummary ),
579+ m ,
580+ )
581+ return
582+ }
583+ }
584+ }
585+
437586 resp .Diagnostics .Append (resp .State .Set (ctx , & data )... )
438587}
439588
@@ -451,7 +600,6 @@ func (r *EndpointResource) Delete(ctx context.Context, req resource.DeleteReques
451600 ctx ,
452601 data .Id .ValueString (),
453602 )
454-
455603 if err != nil {
456604 resp .Diagnostics .AddError (
457605 fmt .Sprintf ("%s - Deleting Endpoint" , utils .ClientErrorSummary ),
0 commit comments