@@ -3,6 +3,7 @@ package port
33import (
44 "context"
55
6+ "github.com/hashicorp/go-cty/cty"
67 "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
78 "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
89 "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
@@ -15,7 +16,7 @@ func newBlueprintResource() *schema.Resource {
1516 return & schema.Resource {
1617 Description : "Port blueprint" ,
1718 CreateContext : createBlueprint ,
18- UpdateContext : createBlueprint ,
19+ UpdateContext : updateBlueprint ,
1920 ReadContext : readBlueprint ,
2021 DeleteContext : deleteBlueprint ,
2122 Schema : map [string ]* schema.Schema {
@@ -68,9 +69,15 @@ func newBlueprintResource() *schema.Resource {
6869 Description : "Whether or not the relation is required" ,
6970 },
7071 "many" : {
71- Type : schema .TypeBool ,
72- Optional : true ,
73- Description : "Whether or not the relation is many" ,
72+ Type : schema .TypeBool ,
73+ Optional : true ,
74+ ValidateDiagFunc : func (i interface {}, path cty.Path ) diag.Diagnostics {
75+ if i .(bool ) {
76+ return diag .Errorf ("Many relations are not supported" )
77+ }
78+ return nil
79+ },
80+ Description : "Unsupported ATM.\n Whether or not the relation is many" ,
7481 },
7582 },
7683 },
@@ -244,8 +251,7 @@ func deleteBlueprint(ctx context.Context, d *schema.ResourceData, m interface{})
244251 return diags
245252}
246253
247- func createRelations (ctx context.Context , d * schema.ResourceData , m interface {}) error {
248- c := m .(* cli.PortClient )
254+ func getRelations (d * schema.ResourceData ) (rel []* cli.Relation ) {
249255 relations , ok := d .GetOk ("relations" )
250256 if ! ok {
251257 return nil
@@ -265,6 +271,18 @@ func createRelations(ctx context.Context, d *schema.ResourceData, m interface{})
265271 if req , ok := relation ["required" ]; ok {
266272 r .Required = req .(bool )
267273 }
274+ if m , ok := relation ["many" ]; ok {
275+ r .Many = m .(bool )
276+ }
277+ rel = append (rel , r )
278+ }
279+ return
280+ }
281+
282+ func createRelations (ctx context.Context , d * schema.ResourceData , m interface {}) error {
283+ c := m .(* cli.PortClient )
284+ rels := getRelations (d )
285+ for _ , r := range rels {
268286 _ , err := c .CreateRelation (ctx , d .Id (), r )
269287 if err != nil {
270288 return err
@@ -273,6 +291,44 @@ func createRelations(ctx context.Context, d *schema.ResourceData, m interface{})
273291 return nil
274292}
275293
294+ func contains (s []string , e string ) bool {
295+ for _ , a := range s {
296+ if a == e {
297+ return true
298+ }
299+ }
300+ return false
301+ }
302+
303+ // patchDeleteDeprecatedRelations deletes relations that are no longer present in the resource.
304+ // This is necessary because we bundled relations inside the blueprint resource.
305+ // In the future, the API of blueprints should support getting the relations and then we can delete this patch.
306+ func patchDeleteDeprecatedRelations (ctx context.Context , d * schema.ResourceData , m interface {}) error {
307+ c := m .(* cli.PortClient )
308+ rels := getRelations (d )
309+ ids := make ([]string , len (rels ))
310+ for i , r := range rels {
311+ ids [i ] = r .Identifier
312+ }
313+ remoteRelations , err := c .ReadRelations (ctx , d .Id ())
314+ if err != nil {
315+ return err
316+ }
317+ toDel := make ([]* cli.Relation , 0 )
318+ for _ , r := range remoteRelations {
319+ if ! contains (ids , r .Identifier ) {
320+ toDel = append (toDel , r )
321+ }
322+ }
323+ for _ , r := range toDel {
324+ err := c .DeleteRelation (ctx , d .Id (), r .Identifier )
325+ if err != nil {
326+ return err
327+ }
328+ }
329+ return nil
330+ }
331+
276332func createBlueprint (ctx context.Context , d * schema.ResourceData , m interface {}) diag.Diagnostics {
277333 var diags diag.Diagnostics
278334 c := m .(* cli.PortClient )
@@ -297,6 +353,34 @@ func createBlueprint(ctx context.Context, d *schema.ResourceData, m interface{})
297353 return diags
298354}
299355
356+ func updateBlueprint (ctx context.Context , d * schema.ResourceData , m interface {}) diag.Diagnostics {
357+ var diags diag.Diagnostics
358+ c := m .(* cli.PortClient )
359+ b , err := blueprintResourceToBody (d )
360+ if err != nil {
361+ return diag .FromErr (err )
362+ }
363+ var bp * cli.Blueprint
364+ if d .Id () != "" {
365+ bp , err = c .UpdateBlueprint (ctx , b , d .Id ())
366+ } else {
367+ bp , err = c .CreateBlueprint (ctx , b )
368+ }
369+ if err != nil {
370+ return diag .FromErr (err )
371+ }
372+ writeBlueprintComputedFieldsToResource (d , bp )
373+ err = patchDeleteDeprecatedRelations (ctx , d , m )
374+ if err != nil {
375+ return diag .FromErr (err )
376+ }
377+ err = createRelations (ctx , d , m )
378+ if err != nil {
379+ return diag .FromErr (err )
380+ }
381+ return diags
382+ }
383+
300384func writeBlueprintComputedFieldsToResource (d * schema.ResourceData , b * cli.Blueprint ) {
301385 d .SetId (b .Identifier )
302386 d .Set ("created_at" , b .CreatedAt .String ())
0 commit comments