github.com/vnpaycloud-console/gophercloud/v2@v2.0.5/openstack/identity/v3/projects/requests.go (about) 1 package projects 2 3 import ( 4 "context" 5 "net/url" 6 "strings" 7 8 "github.com/vnpaycloud-console/gophercloud/v2" 9 "github.com/vnpaycloud-console/gophercloud/v2/pagination" 10 ) 11 12 // ListOptsBuilder allows extensions to add additional parameters to 13 // the List request 14 type ListOptsBuilder interface { 15 ToProjectListQuery() (string, error) 16 } 17 18 // ListOpts enables filtering of a list request. 19 type ListOpts struct { 20 // DomainID filters the response by a domain ID. 21 DomainID string `q:"domain_id"` 22 23 // Enabled filters the response by enabled projects. 24 Enabled *bool `q:"enabled"` 25 26 // IsDomain filters the response by projects that are domains. 27 // Setting this to true is effectively listing domains. 28 IsDomain *bool `q:"is_domain"` 29 30 // Name filters the response by project name. 31 Name string `q:"name"` 32 33 // ParentID filters the response by projects of a given parent project. 34 ParentID string `q:"parent_id"` 35 36 // Tags filters on specific project tags. All tags must be present for the project. 37 Tags string `q:"tags"` 38 39 // TagsAny filters on specific project tags. At least one of the tags must be present for the project. 40 TagsAny string `q:"tags-any"` 41 42 // NotTags filters on specific project tags. All tags must be absent for the project. 43 NotTags string `q:"not-tags"` 44 45 // NotTagsAny filters on specific project tags. At least one of the tags must be absent for the project. 46 NotTagsAny string `q:"not-tags-any"` 47 48 // Filters filters the response by custom filters such as 49 // 'name__contains=foo' 50 Filters map[string]string `q:"-"` 51 } 52 53 // ToProjectListQuery formats a ListOpts into a query string. 54 func (opts ListOpts) ToProjectListQuery() (string, error) { 55 q, err := gophercloud.BuildQueryString(opts) 56 if err != nil { 57 return "", err 58 } 59 60 params := q.Query() 61 for k, v := range opts.Filters { 62 i := strings.Index(k, "__") 63 if i > 0 && i < len(k)-2 { 64 params.Add(k, v) 65 } else { 66 return "", InvalidListFilter{FilterName: k} 67 } 68 } 69 70 q = &url.URL{RawQuery: params.Encode()} 71 return q.String(), err 72 } 73 74 // List enumerates the Projects to which the current token has access. 75 func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { 76 url := listURL(client) 77 if opts != nil { 78 query, err := opts.ToProjectListQuery() 79 if err != nil { 80 return pagination.Pager{Err: err} 81 } 82 url += query 83 } 84 return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { 85 return ProjectPage{pagination.LinkedPageBase{PageResult: r}} 86 }) 87 } 88 89 // ListAvailable enumerates the Projects which are available to a specific user. 90 func ListAvailable(client *gophercloud.ServiceClient) pagination.Pager { 91 url := listAvailableURL(client) 92 return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { 93 return ProjectPage{pagination.LinkedPageBase{PageResult: r}} 94 }) 95 } 96 97 // Get retrieves details on a single project, by ID. 98 func Get(ctx context.Context, client *gophercloud.ServiceClient, id string) (r GetResult) { 99 resp, err := client.Get(ctx, getURL(client, id), &r.Body, nil) 100 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 101 return 102 } 103 104 // CreateOptsBuilder allows extensions to add additional parameters to 105 // the Create request. 106 type CreateOptsBuilder interface { 107 ToProjectCreateMap() (map[string]any, error) 108 } 109 110 // CreateOpts represents parameters used to create a project. 111 type CreateOpts struct { 112 // DomainID is the ID this project will belong under. 113 DomainID string `json:"domain_id,omitempty"` 114 115 // Enabled sets the project status to enabled or disabled. 116 Enabled *bool `json:"enabled,omitempty"` 117 118 // IsDomain indicates if this project is a domain. 119 IsDomain *bool `json:"is_domain,omitempty"` 120 121 // Name is the name of the project. 122 Name string `json:"name" required:"true"` 123 124 // ParentID specifies the parent project of this new project. 125 ParentID string `json:"parent_id,omitempty"` 126 127 // Description is the description of the project. 128 Description string `json:"description,omitempty"` 129 130 // Tags is a list of tags to associate with the project. 131 Tags []string `json:"tags,omitempty"` 132 133 // Extra is free-form extra key/value pairs to describe the project. 134 Extra map[string]any `json:"-"` 135 136 // Options are defined options in the API to enable certain features. 137 Options map[Option]any `json:"options,omitempty"` 138 } 139 140 // ToProjectCreateMap formats a CreateOpts into a create request. 141 func (opts CreateOpts) ToProjectCreateMap() (map[string]any, error) { 142 b, err := gophercloud.BuildRequestBody(opts, "project") 143 144 if err != nil { 145 return nil, err 146 } 147 148 if opts.Extra != nil { 149 if v, ok := b["project"].(map[string]any); ok { 150 for key, value := range opts.Extra { 151 v[key] = value 152 } 153 } 154 } 155 156 return b, nil 157 } 158 159 // Create creates a new Project. 160 func Create(ctx context.Context, client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) { 161 b, err := opts.ToProjectCreateMap() 162 if err != nil { 163 r.Err = err 164 return 165 } 166 resp, err := client.Post(ctx, createURL(client), &b, &r.Body, nil) 167 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 168 return 169 } 170 171 // Delete deletes a project. 172 func Delete(ctx context.Context, client *gophercloud.ServiceClient, projectID string) (r DeleteResult) { 173 resp, err := client.Delete(ctx, deleteURL(client, projectID), nil) 174 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 175 return 176 } 177 178 // UpdateOptsBuilder allows extensions to add additional parameters to 179 // the Update request. 180 type UpdateOptsBuilder interface { 181 ToProjectUpdateMap() (map[string]any, error) 182 } 183 184 // UpdateOpts represents parameters to update a project. 185 type UpdateOpts struct { 186 // DomainID is the ID this project will belong under. 187 DomainID string `json:"domain_id,omitempty"` 188 189 // Enabled sets the project status to enabled or disabled. 190 Enabled *bool `json:"enabled,omitempty"` 191 192 // IsDomain indicates if this project is a domain. 193 IsDomain *bool `json:"is_domain,omitempty"` 194 195 // Name is the name of the project. 196 Name string `json:"name,omitempty"` 197 198 // ParentID specifies the parent project of this new project. 199 ParentID string `json:"parent_id,omitempty"` 200 201 // Description is the description of the project. 202 Description *string `json:"description,omitempty"` 203 204 // Tags is a list of tags to associate with the project. 205 Tags *[]string `json:"tags,omitempty"` 206 207 // Extra is free-form extra key/value pairs to describe the project. 208 Extra map[string]any `json:"-"` 209 210 // Options are defined options in the API to enable certain features. 211 Options map[Option]any `json:"options,omitempty"` 212 } 213 214 // ToUpdateCreateMap formats a UpdateOpts into an update request. 215 func (opts UpdateOpts) ToProjectUpdateMap() (map[string]any, error) { 216 b, err := gophercloud.BuildRequestBody(opts, "project") 217 218 if err != nil { 219 return nil, err 220 } 221 222 if opts.Extra != nil { 223 if v, ok := b["project"].(map[string]any); ok { 224 for key, value := range opts.Extra { 225 v[key] = value 226 } 227 } 228 } 229 230 return b, nil 231 } 232 233 // Update modifies the attributes of a project. 234 func Update(ctx context.Context, client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) { 235 b, err := opts.ToProjectUpdateMap() 236 if err != nil { 237 r.Err = err 238 return 239 } 240 resp, err := client.Patch(ctx, updateURL(client, id), b, &r.Body, &gophercloud.RequestOpts{ 241 OkCodes: []int{200}, 242 }) 243 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 244 return 245 } 246 247 // CheckTags lists tags for a project. 248 func ListTags(ctx context.Context, client *gophercloud.ServiceClient, projectID string) (r ListTagsResult) { 249 resp, err := client.Get(ctx, listTagsURL(client, projectID), &r.Body, &gophercloud.RequestOpts{ 250 OkCodes: []int{200}, 251 }) 252 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 253 return 254 } 255 256 // Tags represents a list of Tags object. 257 type ModifyTagsOpts struct { 258 // Tags is the list of tags associated with the project. 259 Tags []string `json:"tags,omitempty"` 260 } 261 262 // ModifyTagsOptsBuilder allows extensions to add additional parameters to 263 // the Modify request. 264 type ModifyTagsOptsBuilder interface { 265 ToModifyTagsCreateMap() (map[string]any, error) 266 } 267 268 // ToModifyTagsCreateMap formats a ModifyTagsOpts into a Modify tags request. 269 func (opts ModifyTagsOpts) ToModifyTagsCreateMap() (map[string]any, error) { 270 b, err := gophercloud.BuildRequestBody(opts, "") 271 272 if err != nil { 273 return nil, err 274 } 275 return b, nil 276 } 277 278 // ModifyTags deletes all tags of a project and adds new ones. 279 func ModifyTags(ctx context.Context, client *gophercloud.ServiceClient, projectID string, opts ModifyTagsOpts) (r ModifyTagsResult) { 280 281 b, err := opts.ToModifyTagsCreateMap() 282 if err != nil { 283 r.Err = err 284 return 285 } 286 resp, err := client.Put(ctx, modifyTagsURL(client, projectID), b, &r.Body, &gophercloud.RequestOpts{ 287 OkCodes: []int{200}, 288 }) 289 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 290 return 291 } 292 293 // DeleteTag deletes a tag from a project. 294 func DeleteTags(ctx context.Context, client *gophercloud.ServiceClient, projectID string) (r DeleteTagsResult) { 295 resp, err := client.Delete(ctx, deleteTagsURL(client, projectID), &gophercloud.RequestOpts{ 296 OkCodes: []int{204}, 297 }) 298 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 299 return 300 }