github.com/akamai/AkamaiOPEN-edgegrid-golang/v2@v2.17.0/pkg/papi/propertyversion.go (about) 1 package papi 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "net/http" 8 "strconv" 9 10 "github.com/akamai/AkamaiOPEN-edgegrid-golang/v2/pkg/edgegriderr" 11 validation "github.com/go-ozzo/ozzo-validation/v4" 12 ) 13 14 type ( 15 // PropertyVersions contains operations available on PropertyVersions resource 16 // See: https://developer.akamai.com/api/core_features/property_manager/v1.html#propertyversionsgroup 17 PropertyVersions interface { 18 // GetPropertyVersions fetches available property versions 19 // See: https://developer.akamai.com/api/core_features/property_manager/v1.html#getpropertyversions 20 GetPropertyVersions(context.Context, GetPropertyVersionsRequest) (*GetPropertyVersionsResponse, error) 21 22 // GetPropertyVersion fetches specific property version 23 // See: https://developer.akamai.com/api/core_features/property_manager/v1.html#getpropertyversion 24 GetPropertyVersion(context.Context, GetPropertyVersionRequest) (*GetPropertyVersionsResponse, error) 25 26 // CreatePropertyVersion creates a new property version 27 // See: https://developer.akamai.com/api/core_features/property_manager/v1.html#postpropertyversions 28 CreatePropertyVersion(context.Context, CreatePropertyVersionRequest) (*CreatePropertyVersionResponse, error) 29 30 // GetLatestVersion fetches latest property version 31 // See: https://developer.akamai.com/api/core_features/property_manager/v1.html#getlatestversion 32 GetLatestVersion(context.Context, GetLatestVersionRequest) (*GetPropertyVersionsResponse, error) 33 34 // GetAvailableBehaviors fetches a list of behaviors applied to property version 35 // See: https://developer.akamai.com/api/core_features/property_manager/v1.html#getavailablebehaviors 36 GetAvailableBehaviors(context.Context, GetFeaturesRequest) (*GetFeaturesCriteriaResponse, error) 37 38 // GetAvailableCriteria fetches a list of criteria applied to property version 39 // See: https://developer.akamai.com/api/core_features/property_manager/v1.html#getavailablecriteria 40 GetAvailableCriteria(context.Context, GetFeaturesRequest) (*GetFeaturesCriteriaResponse, error) 41 } 42 43 // GetPropertyVersionsRequest contains path and query params used for listing property versions 44 GetPropertyVersionsRequest struct { 45 PropertyID string 46 ContractID string 47 GroupID string 48 Limit int 49 Offset int 50 } 51 52 // GetPropertyVersionsResponse contains GET response returned while fetching property versions or specific version 53 GetPropertyVersionsResponse struct { 54 PropertyID string `json:"propertyId"` 55 PropertyName string `json:"propertyName"` 56 AccountID string `json:"accountId"` 57 ContractID string `json:"contractId"` 58 GroupID string `json:"groupId"` 59 AssetID string `json:"assetId"` 60 Versions PropertyVersionItems `json:"versions"` 61 Version PropertyVersionGetItem 62 } 63 64 // PropertyVersionItems contains collection of property version details 65 PropertyVersionItems struct { 66 Items []PropertyVersionGetItem `json:"items"` 67 } 68 69 // PropertyVersionGetItem contains detailed information about specific property version returned in GET 70 PropertyVersionGetItem struct { 71 Etag string `json:"etag"` 72 Note string `json:"note"` 73 ProductID string `json:"productId"` 74 ProductionStatus VersionStatus `json:"productionStatus"` 75 PropertyVersion int `json:"propertyVersion"` 76 RuleFormat string `json:"ruleFormat"` 77 StagingStatus VersionStatus `json:"stagingStatus"` 78 UpdatedByUser string `json:"updatedByUser"` 79 UpdatedDate string `json:"updatedDate"` 80 } 81 82 // GetPropertyVersionRequest contains path and query params used for fetching specific property version 83 GetPropertyVersionRequest struct { 84 PropertyID string 85 PropertyVersion int 86 ContractID string 87 GroupID string 88 } 89 90 // CreatePropertyVersionRequest contains path and query params, as well as request body required to execute POST /versions request 91 CreatePropertyVersionRequest struct { 92 PropertyID string 93 ContractID string 94 GroupID string 95 Version PropertyVersionCreate 96 } 97 98 // PropertyVersionCreate contains request body used in POST /versions request 99 PropertyVersionCreate struct { 100 CreateFromVersion int `json:"createFromVersion"` 101 CreateFromVersionEtag string `json:"createFromVersionEtag,omitempty"` 102 } 103 104 // CreatePropertyVersionResponse contains a link returned after creating new property version and version number of this version 105 CreatePropertyVersionResponse struct { 106 VersionLink string `json:"versionLink"` 107 PropertyVersion int 108 } 109 110 // GetLatestVersionRequest contains path and query params required to fetch latest property version 111 GetLatestVersionRequest struct { 112 PropertyID string 113 ActivatedOn string 114 ContractID string 115 GroupID string 116 } 117 118 // GetFeaturesRequest contains path and query params required to fetch both available behaviors and available criteria for a property 119 GetFeaturesRequest struct { 120 PropertyID string 121 PropertyVersion int 122 ContractID string 123 GroupID string 124 } 125 126 // AvailableFeature represents details of a single feature (behavior or criteria available for selected property version 127 AvailableFeature struct { 128 Name string `json:"name"` 129 SchemaLink string `json:"schemaLink"` 130 } 131 132 // GetFeaturesCriteriaResponse contains response received when fetching both available behaviors and available criteria for a property 133 GetFeaturesCriteriaResponse struct { 134 ContractID string `json:"contractId"` 135 GroupID string `json:"groupId"` 136 ProductID string `json:"productId"` 137 RuleFormat string `json:"ruleFormat"` 138 AvailableBehaviors AvailableFeatureItems `json:"availableBehaviors"` 139 } 140 141 // AvailableFeatureItems contains a slice of AvailableFeature items 142 AvailableFeatureItems struct { 143 Items []AvailableFeature `json:"items"` 144 } 145 146 // VersionStatus represents ProductionVersion and StagingVersion of a Version struct 147 VersionStatus string 148 ) 149 150 const ( 151 // VersionStatusActive const 152 VersionStatusActive VersionStatus = "ACTIVE" 153 // VersionStatusInactive const 154 VersionStatusInactive VersionStatus = "INACTIVE" 155 // VersionStatusPending const 156 VersionStatusPending VersionStatus = "PENDING" 157 // VersionStatusDeactivated const 158 VersionStatusDeactivated VersionStatus = "DEACTIVATED" 159 // VersionProduction const 160 VersionProduction = "PRODUCTION" 161 // VersionStaging const 162 VersionStaging = "STAGING" 163 ) 164 165 // Validate validates GetPropertyVersionsRequest 166 func (v GetPropertyVersionsRequest) Validate() error { 167 return validation.Errors{ 168 "PropertyID": validation.Validate(v.PropertyID, validation.Required), 169 }.Filter() 170 } 171 172 // Validate validates GetPropertyVersionRequest 173 func (v GetPropertyVersionRequest) Validate() error { 174 return validation.Errors{ 175 "PropertyID": validation.Validate(v.PropertyID, validation.Required), 176 "PropertyVersion": validation.Validate(v.PropertyVersion, validation.Required), 177 }.Filter() 178 } 179 180 // Validate validates CreatePropertyVersionRequest 181 func (v CreatePropertyVersionRequest) Validate() error { 182 errs := validation.Errors{ 183 "PropertyID": validation.Validate(v.PropertyID, validation.Required), 184 "Version": validation.Validate(v.Version), 185 } 186 return edgegriderr.ParseValidationErrors(errs) 187 } 188 189 // Validate validates PropertyVersionCreate 190 func (v PropertyVersionCreate) Validate() error { 191 return validation.Errors{ 192 "CreateFromVersion": validation.Validate(v.CreateFromVersion, validation.Required), 193 }.Filter() 194 } 195 196 // Validate validates GetLatestVersionRequest 197 func (v GetLatestVersionRequest) Validate() error { 198 return validation.Errors{ 199 "PropertyID": validation.Validate(v.PropertyID, validation.Required), 200 "ActivatedOn": validation.Validate(v.ActivatedOn, validation.In(VersionProduction, VersionStaging)), 201 }.Filter() 202 } 203 204 // Validate validates GetFeaturesRequest 205 func (v GetFeaturesRequest) Validate() error { 206 return validation.Errors{ 207 "PropertyID": validation.Validate(v.PropertyID, validation.Required), 208 "PropertyVersion": validation.Validate(v.PropertyVersion, validation.Required), 209 }.Filter() 210 } 211 212 var ( 213 // ErrGetPropertyVersions represents error when fetching property versions fails 214 ErrGetPropertyVersions = errors.New("fetching property versions") 215 // ErrGetPropertyVersion represents error when fetching property version fails 216 ErrGetPropertyVersion = errors.New("fetching property version") 217 // ErrGetLatestVersion represents error when fetching latest property version fails 218 ErrGetLatestVersion = errors.New("fetching latest property version") 219 // ErrCreatePropertyVersion represents error when creating property version fails 220 ErrCreatePropertyVersion = errors.New("creating property version") 221 // ErrGetAvailableBehaviors represents error when fetching available behaviors fails 222 ErrGetAvailableBehaviors = errors.New("fetching available behaviors") 223 // ErrGetAvailableCriteria represents error when fetching available criteria fails 224 ErrGetAvailableCriteria = errors.New("fetching available criteria") 225 ) 226 227 // GetPropertyVersions returns list of property versions for give propertyID, contractID and groupID 228 func (p *papi) GetPropertyVersions(ctx context.Context, params GetPropertyVersionsRequest) (*GetPropertyVersionsResponse, error) { 229 if err := params.Validate(); err != nil { 230 return nil, fmt.Errorf("%s: %w: %s", ErrGetPropertyVersions, ErrStructValidation, err) 231 } 232 233 logger := p.Log(ctx) 234 logger.Debug("GetPropertyVersions") 235 236 getURL := fmt.Sprintf( 237 "/papi/v1/properties/%s/versions?contractId=%s&groupId=%s", 238 params.PropertyID, 239 params.ContractID, 240 params.GroupID, 241 ) 242 if params.Limit != 0 { 243 getURL += fmt.Sprintf("&limit=%d", params.Limit) 244 } 245 if params.Offset != 0 { 246 getURL += fmt.Sprintf("&offset=%d", params.Offset) 247 } 248 req, err := http.NewRequestWithContext(ctx, http.MethodGet, getURL, nil) 249 if err != nil { 250 return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetPropertyVersions, err) 251 } 252 253 var versions GetPropertyVersionsResponse 254 resp, err := p.Exec(req, &versions) 255 if err != nil { 256 return nil, fmt.Errorf("%w: request failed: %s", ErrGetPropertyVersions, err) 257 } 258 259 if resp.StatusCode != http.StatusOK { 260 return nil, fmt.Errorf("%s: %w", ErrGetPropertyVersions, p.Error(resp)) 261 } 262 263 return &versions, nil 264 } 265 266 // GetLatestVersion returns either the latest property version overall, or the latest ACTIVE version on production or staging network 267 func (p *papi) GetLatestVersion(ctx context.Context, params GetLatestVersionRequest) (*GetPropertyVersionsResponse, error) { 268 if err := params.Validate(); err != nil { 269 return nil, fmt.Errorf("%s: %w: %s", ErrGetLatestVersion, ErrStructValidation, err) 270 } 271 272 logger := p.Log(ctx) 273 logger.Debug("GetLatestVersion") 274 275 getURL := fmt.Sprintf( 276 "/papi/v1/properties/%s/versions/latest?contractId=%s&groupId=%s", 277 params.PropertyID, 278 params.ContractID, 279 params.GroupID, 280 ) 281 if params.ActivatedOn != "" { 282 getURL += fmt.Sprintf("&activatedOn=%s", params.ActivatedOn) 283 } 284 req, err := http.NewRequestWithContext(ctx, http.MethodGet, getURL, nil) 285 if err != nil { 286 return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetLatestVersion, err) 287 } 288 289 var version GetPropertyVersionsResponse 290 resp, err := p.Exec(req, &version) 291 if err != nil { 292 return nil, fmt.Errorf("%w: request failed: %s", ErrGetLatestVersion, err) 293 } 294 295 if resp.StatusCode != http.StatusOK { 296 return nil, fmt.Errorf("%s: %w", ErrGetLatestVersion, p.Error(resp)) 297 } 298 if len(version.Versions.Items) == 0 { 299 return nil, fmt.Errorf("%s: %w: latest version for PropertyID: %s", ErrGetLatestVersion, ErrNotFound, params.PropertyID) 300 } 301 version.Version = version.Versions.Items[0] 302 return &version, nil 303 } 304 305 // GetPropertyVersion returns property version with provided version number 306 func (p *papi) GetPropertyVersion(ctx context.Context, params GetPropertyVersionRequest) (*GetPropertyVersionsResponse, error) { 307 if err := params.Validate(); err != nil { 308 return nil, fmt.Errorf("%s: %w: %s", ErrGetPropertyVersion, ErrStructValidation, err) 309 } 310 311 logger := p.Log(ctx) 312 logger.Debug("GetPropertyVersion") 313 314 getURL := fmt.Sprintf( 315 "/papi/v1/properties/%s/versions/%d?contractId=%s&groupId=%s", 316 params.PropertyID, 317 params.PropertyVersion, 318 params.ContractID, 319 params.GroupID, 320 ) 321 req, err := http.NewRequestWithContext(ctx, http.MethodGet, getURL, nil) 322 if err != nil { 323 return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetPropertyVersion, err) 324 } 325 326 var versions GetPropertyVersionsResponse 327 resp, err := p.Exec(req, &versions) 328 if err != nil { 329 return nil, fmt.Errorf("%w: request failed: %s", ErrGetPropertyVersion, err) 330 } 331 332 if resp.StatusCode != http.StatusOK { 333 return nil, fmt.Errorf("%s: %w", ErrGetPropertyVersion, p.Error(resp)) 334 } 335 if len(versions.Versions.Items) == 0 { 336 return nil, fmt.Errorf("%s: %w: Version %d for PropertyID: %s", ErrGetPropertyVersion, ErrNotFound, params.PropertyVersion, params.PropertyID) 337 } 338 versions.Version = versions.Versions.Items[0] 339 return &versions, nil 340 } 341 342 // CreatePropertyVersion creates a new property version and returns location and number for the new version 343 func (p *papi) CreatePropertyVersion(ctx context.Context, request CreatePropertyVersionRequest) (*CreatePropertyVersionResponse, error) { 344 if err := request.Validate(); err != nil { 345 return nil, fmt.Errorf("%s: %w:\n%s", ErrCreatePropertyVersion, ErrStructValidation, err) 346 } 347 348 logger := p.Log(ctx) 349 logger.Debug("CreatePropertyVersion") 350 351 getURL := fmt.Sprintf( 352 "/papi/v1/properties/%s/versions?contractId=%s&groupId=%s", 353 request.PropertyID, 354 request.ContractID, 355 request.GroupID, 356 ) 357 req, err := http.NewRequestWithContext(ctx, http.MethodPost, getURL, nil) 358 if err != nil { 359 return nil, fmt.Errorf("%w: failed to create request: %s", ErrCreatePropertyVersion, err) 360 } 361 362 var version CreatePropertyVersionResponse 363 resp, err := p.Exec(req, &version, request.Version) 364 if err != nil { 365 return nil, fmt.Errorf("%w: request failed: %s", ErrCreatePropertyVersion, err) 366 } 367 368 if resp.StatusCode != http.StatusCreated { 369 return nil, fmt.Errorf("%s: %w", ErrCreatePropertyVersion, p.Error(resp)) 370 } 371 propertyVersion, err := ResponseLinkParse(version.VersionLink) 372 if err != nil { 373 return nil, fmt.Errorf("%s: %w: %s", ErrCreatePropertyVersion, ErrInvalidResponseLink, err) 374 } 375 versionNumber, err := strconv.Atoi(propertyVersion) 376 if err != nil { 377 return nil, fmt.Errorf("%s: %w: %s: %s", ErrCreatePropertyVersion, ErrInvalidResponseLink, "version should be a number", propertyVersion) 378 } 379 version.PropertyVersion = versionNumber 380 return &version, nil 381 } 382 383 // GetAvailableBehaviors lists available behaviors for given property version 384 func (p *papi) GetAvailableBehaviors(ctx context.Context, params GetFeaturesRequest) (*GetFeaturesCriteriaResponse, error) { 385 if err := params.Validate(); err != nil { 386 return nil, fmt.Errorf("%s: %w: %s", ErrGetAvailableBehaviors, ErrStructValidation, err) 387 } 388 389 logger := p.Log(ctx) 390 logger.Debug("GetAvailableBehaviors") 391 392 getURL := fmt.Sprintf( 393 "/papi/v1/properties/%s/versions/%d/available-behaviors?contractId=%s&groupId=%s", 394 params.PropertyID, 395 params.PropertyVersion, 396 params.ContractID, 397 params.GroupID, 398 ) 399 req, err := http.NewRequestWithContext(ctx, http.MethodGet, getURL, nil) 400 if err != nil { 401 return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetAvailableBehaviors, err) 402 } 403 404 var versions GetFeaturesCriteriaResponse 405 resp, err := p.Exec(req, &versions) 406 if err != nil { 407 return nil, fmt.Errorf("%w: request failed: %s", ErrGetAvailableBehaviors, err) 408 } 409 410 if resp.StatusCode != http.StatusOK { 411 return nil, fmt.Errorf("%s: %w", ErrGetAvailableBehaviors, p.Error(resp)) 412 } 413 414 return &versions, nil 415 } 416 417 // GetAvailableCriteria lists available criteria for given property version 418 func (p *papi) GetAvailableCriteria(ctx context.Context, params GetFeaturesRequest) (*GetFeaturesCriteriaResponse, error) { 419 if err := params.Validate(); err != nil { 420 return nil, fmt.Errorf("%s: %w: %s", ErrGetAvailableCriteria, ErrStructValidation, err) 421 } 422 423 logger := p.Log(ctx) 424 logger.Debug("GetAvailableCriteria") 425 426 getURL := fmt.Sprintf( 427 "/papi/v1/properties/%s/versions/%d/available-criteria?contractId=%s&groupId=%s", 428 params.PropertyID, 429 params.PropertyVersion, 430 params.ContractID, 431 params.GroupID, 432 ) 433 req, err := http.NewRequestWithContext(ctx, http.MethodGet, getURL, nil) 434 if err != nil { 435 return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetAvailableCriteria, err) 436 } 437 438 var versions GetFeaturesCriteriaResponse 439 resp, err := p.Exec(req, &versions) 440 if err != nil { 441 return nil, fmt.Errorf("%w: request failed: %s", ErrGetAvailableCriteria, err) 442 } 443 444 if resp.StatusCode != http.StatusOK { 445 return nil, fmt.Errorf("%s: %w", ErrGetAvailableCriteria, p.Error(resp)) 446 } 447 448 return &versions, nil 449 }