2020package cloudstack
2121
2222import (
23+ "encoding/json"
2324 "fmt"
2425 "log"
26+ "regexp"
27+ "strings"
2528
2629 "github.com/apache/cloudstack-go/v2/cloudstack"
2730 "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -33,15 +36,14 @@ func dataSourceCloudstackRole() *schema.Resource {
3336 Schema : map [string ]* schema.Schema {
3437 "filter" : dataSourceFiltersSchema (),
3538
39+ //Computed values
3640 "id" : {
3741 Type : schema .TypeString ,
38- Optional : true ,
3942 Computed : true ,
4043 },
4144
4245 "name" : {
4346 Type : schema .TypeString ,
44- Optional : true ,
4547 Computed : true ,
4648 },
4749
@@ -65,24 +67,36 @@ func dataSourceCloudstackRole() *schema.Resource {
6567
6668func dataSourceCloudstackRoleRead (d * schema.ResourceData , meta interface {}) error {
6769 cs := meta .(* cloudstack.CloudStackClient )
70+ p := cs .Role .NewListRolesParams ()
6871
69- var err error
72+ csRoles , err := cs .Role .ListRoles (p )
73+ if err != nil {
74+ return fmt .Errorf ("failed to list roles: %s" , err )
75+ }
76+
77+ filters := d .Get ("filter" )
7078 var role * cloudstack.Role
7179
72- if id , ok := d .GetOk ("id" ); ok {
73- log .Printf ("[DEBUG] Getting Role by ID: %s" , id .(string ))
74- role , _ , err = cs .Role .GetRoleByID (id .(string ))
75- } else if name , ok := d .GetOk ("name" ); ok {
76- log .Printf ("[DEBUG] Getting Role by name: %s" , name .(string ))
77- role , _ , err = cs .Role .GetRoleByName (name .(string ))
78- } else {
79- return fmt .Errorf ("Either 'id' or 'name' must be specified" )
80+ for _ , r := range csRoles .Roles {
81+ match , err := applyRoleFilters (r , filters .(* schema.Set ))
82+ if err != nil {
83+ return err
84+ }
85+ if match {
86+ role = r
87+ break
88+ }
8089 }
8190
82- if err ! = nil {
83- return err
91+ if role = = nil {
92+ return fmt . Errorf ( "no role is matching with the specified criteria" )
8493 }
94+ log .Printf ("[DEBUG] Selected role: %s\n " , role .Name )
95+
96+ return roleDescriptionAttributes (d , role )
97+ }
8598
99+ func roleDescriptionAttributes (d * schema.ResourceData , role * cloudstack.Role ) error {
86100 d .SetId (role .Id )
87101 d .Set ("name" , role .Name )
88102 d .Set ("type" , role .Type )
@@ -91,3 +105,55 @@ func dataSourceCloudstackRoleRead(d *schema.ResourceData, meta interface{}) erro
91105
92106 return nil
93107}
108+
109+ func latestRole (roles []* cloudstack.Role ) (* cloudstack.Role , error ) {
110+ // Since the Role struct doesn't have a Created field,
111+ // we'll just return the first role in the list
112+ if len (roles ) > 0 {
113+ return roles [0 ], nil
114+ }
115+ return nil , fmt .Errorf ("no roles found" )
116+ }
117+
118+ func applyRoleFilters (role * cloudstack.Role , filters * schema.Set ) (bool , error ) {
119+ var roleJSON map [string ]interface {}
120+ k , _ := json .Marshal (role )
121+ err := json .Unmarshal (k , & roleJSON )
122+ if err != nil {
123+ return false , err
124+ }
125+
126+ for _ , f := range filters .List () {
127+ m := f .(map [string ]interface {})
128+ r , err := regexp .Compile (m ["value" ].(string ))
129+ if err != nil {
130+ return false , fmt .Errorf ("invalid regex: %s" , err )
131+ }
132+ updatedName := strings .ReplaceAll (m ["name" ].(string ), "_" , "" )
133+
134+ // Check if the field exists in the role JSON
135+ roleField , ok := roleJSON [updatedName ]
136+ if ! ok {
137+ return false , fmt .Errorf ("field %s does not exist in role" , updatedName )
138+ }
139+
140+ // Convert the field to string for regex matching
141+ var roleFieldStr string
142+ switch v := roleField .(type ) {
143+ case string :
144+ roleFieldStr = v
145+ case bool :
146+ roleFieldStr = fmt .Sprintf ("%t" , v )
147+ case float64 :
148+ roleFieldStr = fmt .Sprintf ("%g" , v )
149+ default :
150+ roleFieldStr = fmt .Sprintf ("%v" , v )
151+ }
152+
153+ if ! r .MatchString (roleFieldStr ) {
154+ return false , nil
155+ }
156+ }
157+
158+ return true , nil
159+ }
0 commit comments