github.com/akamai/AkamaiOPEN-edgegrid-golang/v2@v2.17.0/pkg/configgtm/property.go (about) 1 package gtm 2 3 import ( 4 "context" 5 "fmt" 6 "net/http" 7 ) 8 9 // 10 // Support gtm domain properties thru Edgegrid 11 // Based on 1.4 Schema 12 // 13 14 // Properties contains operations available on a Property resource 15 // See: https://developer.akamai.com/api/web_performance/global_traffic_management/v1.html 16 type Properties interface { 17 // NewTrafficTarget is a method applied to a property object that instantiates a TrafficTarget object. 18 NewTrafficTarget(context.Context) *TrafficTarget 19 // NewStaticRRSet is a method applied to a property object that instantiates a StaticRRSet object. 20 NewStaticRRSet(context.Context) *StaticRRSet 21 // NewLivenessTest is a method applied to a property object that instantiates a LivenessTest object. 22 NewLivenessTest(context.Context, string, string, int, float32) *LivenessTest 23 // NewProperty creates a new Property object. 24 NewProperty(context.Context, string) *Property 25 // ListProperties retreieves all Properties for the provided domainName. 26 // See: https://developer.akamai.com/api/web_performance/global_traffic_management/v1.html#getproperties 27 ListProperties(context.Context, string) ([]*Property, error) 28 // GetProperty retrieves a Property with the given domain and property names. 29 // See: https://developer.akamai.com/api/web_performance/global_traffic_management/v1.html#getproperty 30 GetProperty(context.Context, string, string) (*Property, error) 31 // CreateProperty creates property 32 // See: https://developer.akamai.com/api/web_performance/global_traffic_management/v1.html#putproperty 33 CreateProperty(context.Context, *Property, string) (*PropertyResponse, error) 34 // DeleteProperty is a method applied to a property object resulting in removal. 35 // See: https://developer.akamai.com/api/web_performance/global_traffic_management/v1.html#deleteproperty 36 DeleteProperty(context.Context, *Property, string) (*ResponseStatus, error) 37 // UpdateProperty is a method applied to a property object resulting in an update. 38 // https://developer.akamai.com/api/web_performance/global_traffic_management/v1.html#putproperty 39 UpdateProperty(context.Context, *Property, string) (*ResponseStatus, error) 40 } 41 42 // TrafficTarget struct contains information about where to direct data center traffic 43 type TrafficTarget struct { 44 DatacenterId int `json:"datacenterId"` 45 Enabled bool `json:"enabled"` 46 Weight float64 `json:"weight,omitempty"` 47 Servers []string `json:"servers,omitempty"` 48 Name string `json:"name,omitempty"` 49 HandoutCName string `json:"handoutCName,omitempty"` 50 } 51 52 // HttpHeader struct contains HTTP headers to send if the testObjectProtocol is http or https 53 type HttpHeader struct { 54 Name string `json:"name"` 55 Value string `json:"value"` 56 } 57 58 // LivenessTest contains configuration of liveness tests to determine whether your servers respond to requests 59 type LivenessTest struct { 60 Name string `json:"name"` 61 ErrorPenalty float64 `json:"errorPenalty,omitempty"` 62 PeerCertificateVerification bool `json:"peerCertificateVerification"` 63 TestInterval int `json:"testInterval,omitempty"` 64 TestObject string `json:"testObject,omitempty"` 65 Links []*Link `json:"links,omitempty"` 66 RequestString string `json:"requestString,omitempty"` 67 ResponseString string `json:"responseString,omitempty"` 68 HttpError3xx bool `json:"httpError3xx"` 69 HttpError4xx bool `json:"httpError4xx"` 70 HttpError5xx bool `json:"httpError5xx"` 71 Disabled bool `json:"disabled"` 72 TestObjectProtocol string `json:"testObjectProtocol,omitempty"` 73 TestObjectPassword string `json:"testObjectPassword,omitempty"` 74 TestObjectPort int `json:"testObjectPort,omitempty"` 75 SslClientPrivateKey string `json:"sslClientPrivateKey,omitempty"` 76 SslClientCertificate string `json:"sslClientCertificate,omitempty"` 77 DisableNonstandardPortWarning bool `json:"disableNonstandardPortWarning"` 78 HttpHeaders []*HttpHeader `json:"httpHeaders,omitempty"` 79 TestObjectUsername string `json:"testObjectUsername,omitempty"` 80 TestTimeout float32 `json:"testTimeout,omitempty"` 81 TimeoutPenalty float64 `json:"timeoutPenalty,omitempty"` 82 AnswersRequired bool `json:"answersRequired"` 83 ResourceType string `json:"resourceType,omitempty"` 84 RecursionRequested bool `json:"recursionRequested"` 85 } 86 87 // StaticRRSet contains static recordset 88 type StaticRRSet struct { 89 Type string `json:"type"` 90 TTL int `json:"ttl"` 91 Rdata []string `json:"rdata"` 92 } 93 94 // Property represents a GTM property 95 type Property struct { 96 Name string `json:"name"` 97 Type string `json:"type"` 98 Ipv6 bool `json:"ipv6"` 99 ScoreAggregationType string `json:"scoreAggregationType"` 100 StickinessBonusPercentage int `json:"stickinessBonusPercentage,omitempty"` 101 StickinessBonusConstant int `json:"stickinessBonusConstant,omitempty"` 102 HealthThreshold float64 `json:"healthThreshold,omitempty"` 103 UseComputedTargets bool `json:"useComputedTargets"` 104 BackupIp string `json:"backupIp,omitempty"` 105 BalanceByDownloadScore bool `json:"balanceByDownloadScore"` 106 StaticTTL int `json:"staticTTL,omitempty"` 107 StaticRRSets []*StaticRRSet `json:"staticRRSets,omitempty"` 108 LastModified string `json:"lastModified"` 109 UnreachableThreshold float64 `json:"unreachableThreshold,omitempty"` 110 MinLiveFraction float64 `json:"minLiveFraction,omitempty"` 111 HealthMultiplier float64 `json:"healthMultiplier,omitempty"` 112 DynamicTTL int `json:"dynamicTTL,omitempty"` 113 MaxUnreachablePenalty int `json:"maxUnreachablePenalty,omitempty"` 114 MapName string `json:"mapName,omitempty"` 115 HandoutLimit int `json:"handoutLimit"` 116 HandoutMode string `json:"handoutMode"` 117 FailoverDelay int `json:"failoverDelay,omitempty"` 118 BackupCName string `json:"backupCName,omitempty"` 119 FailbackDelay int `json:"failbackDelay,omitempty"` 120 LoadImbalancePercentage float64 `json:"loadImbalancePercentage,omitempty"` 121 HealthMax float64 `json:"healthMax,omitempty"` 122 GhostDemandReporting bool `json:"ghostDemandReporting"` 123 Comments string `json:"comments,omitempty"` 124 CName string `json:"cname,omitempty"` 125 WeightedHashBitsForIPv4 int `json:"weightedHashBitsForIPv4,omitempty"` 126 WeightedHashBitsForIPv6 int `json:"weightedHashBitsForIPv6,omitempty"` 127 TrafficTargets []*TrafficTarget `json:"trafficTargets,omitempty"` 128 Links []*Link `json:"links,omitempty"` 129 LivenessTests []*LivenessTest `json:"livenessTests,omitempty"` 130 } 131 132 // PropertyList contains a list of property items 133 type PropertyList struct { 134 PropertyItems []*Property `json:"items"` 135 } 136 137 // Validate validates Property 138 func (prop *Property) Validate() error { 139 140 if len(prop.Name) < 1 { 141 return fmt.Errorf("Property is missing Name") 142 } 143 if len(prop.Type) < 1 { 144 return fmt.Errorf("Property is missing Type") 145 } 146 if len(prop.ScoreAggregationType) < 1 { 147 return fmt.Errorf("Property is missing ScoreAggregationType") 148 } 149 if len(prop.HandoutMode) < 1 { 150 return fmt.Errorf("Property is missing HandoutMode") 151 } 152 // is zero a valid value? need to check and uncomment 153 //if prop.HandoutLimit == 0 { 154 // return fmt.Errorf("Property is missing handoutLimit" 155 //} 156 157 return nil 158 } 159 160 // NewTrafficTarget is a method applied to a property object that instantiates a TrafficTarget object. 161 func (p *gtm) NewTrafficTarget(ctx context.Context) *TrafficTarget { 162 163 logger := p.Log(ctx) 164 logger.Debug("NewTrafficTarget") 165 166 return &TrafficTarget{} 167 168 } 169 170 // NewStaticRRSet is a method applied to a property object that instantiates a StaticRRSet object. 171 func (p *gtm) NewStaticRRSet(ctx context.Context) *StaticRRSet { 172 173 logger := p.Log(ctx) 174 logger.Debug("NewStaticRRSet") 175 176 return &StaticRRSet{} 177 178 } 179 180 // NewHttpHeader is a method applied to a livenesstest object that instantiates an HttpHeader object. 181 func (lt *LivenessTest) NewHttpHeader() *HttpHeader { 182 183 return &HttpHeader{} 184 185 } 186 187 // NewLivenessTest is a method applied to a property object that instantiates a LivenessTest object. 188 func (p *gtm) NewLivenessTest(ctx context.Context, name string, objproto string, interval int, timeout float32) *LivenessTest { 189 190 logger := p.Log(ctx) 191 logger.Debug("NewLivenessTest") 192 193 return &LivenessTest{Name: name, TestInterval: interval, TestObjectProtocol: objproto, TestTimeout: timeout} 194 195 } 196 197 // NewProperty creates a new Property object. 198 func (p *gtm) NewProperty(ctx context.Context, name string) *Property { 199 200 logger := p.Log(ctx) 201 logger.Debug("NewProperty") 202 203 property := &Property{Name: name} 204 return property 205 } 206 207 // ListProperties retreieves all Properties for the provided domainName. 208 func (p *gtm) ListProperties(ctx context.Context, domainName string) ([]*Property, error) { 209 210 logger := p.Log(ctx) 211 logger.Debug("ListProperties") 212 213 var properties PropertyList 214 getURL := fmt.Sprintf("/config-gtm/v1/domains/%s/properties", domainName) 215 req, err := http.NewRequestWithContext(ctx, http.MethodGet, getURL, nil) 216 if err != nil { 217 return nil, fmt.Errorf("failed to create ListProperties request: %w", err) 218 } 219 setVersionHeader(req, schemaVersion) 220 resp, err := p.Exec(req, &properties) 221 if err != nil { 222 return nil, fmt.Errorf("ListProperties request failed: %w", err) 223 } 224 225 if resp.StatusCode != http.StatusOK { 226 return nil, p.Error(resp) 227 } 228 229 return properties.PropertyItems, nil 230 } 231 232 // GetProperty retrieves a Property with the given name. 233 func (p *gtm) GetProperty(ctx context.Context, name, domainName string) (*Property, error) { 234 235 logger := p.Log(ctx) 236 logger.Debug("GetProperty") 237 238 var property Property 239 getURL := fmt.Sprintf("/config-gtm/v1/domains/%s/properties/%s", domainName, name) 240 req, err := http.NewRequestWithContext(ctx, http.MethodGet, getURL, nil) 241 if err != nil { 242 return nil, fmt.Errorf("failed to create GetProperty request: %w", err) 243 } 244 setVersionHeader(req, schemaVersion) 245 resp, err := p.Exec(req, &property) 246 if err != nil { 247 return nil, fmt.Errorf("GetProperty request failed: %w", err) 248 } 249 250 if resp.StatusCode != http.StatusOK { 251 return nil, p.Error(resp) 252 } 253 254 return &property, nil 255 } 256 257 // Create the property in the receiver argument in the specified domain. 258 func (p *gtm) CreateProperty(ctx context.Context, property *Property, domainName string) (*PropertyResponse, error) { 259 260 logger := p.Log(ctx) 261 logger.Debug("CreateProperty") 262 263 // Need do any validation? 264 return property.save(ctx, p, domainName) 265 } 266 267 // Update the property in the receiver argument in the specified domain. 268 func (p *gtm) UpdateProperty(ctx context.Context, property *Property, domainName string) (*ResponseStatus, error) { 269 270 logger := p.Log(ctx) 271 logger.Debug("UpdateProperty") 272 273 // Need do any validation? 274 stat, err := property.save(ctx, p, domainName) 275 if err != nil { 276 return nil, err 277 } 278 return stat.Status, err 279 280 } 281 282 // Save Property updates method 283 func (prop *Property) save(ctx context.Context, p *gtm, domainName string) (*PropertyResponse, error) { 284 285 if err := prop.Validate(); err != nil { 286 return nil, fmt.Errorf("Property validation failed. %w", err) 287 } 288 289 putURL := fmt.Sprintf("/config-gtm/v1/domains/%s/properties/%s", domainName, prop.Name) 290 req, err := http.NewRequestWithContext(ctx, http.MethodPut, putURL, nil) 291 if err != nil { 292 return nil, fmt.Errorf("failed to create Property request: %w", err) 293 } 294 295 var presp PropertyResponse 296 setVersionHeader(req, schemaVersion) 297 resp, err := p.Exec(req, &presp, prop) 298 if err != nil { 299 return nil, fmt.Errorf("Property request failed: %w", err) 300 } 301 302 if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated { 303 return nil, p.Error(resp) 304 } 305 306 return &presp, nil 307 } 308 309 // Delete the property identified by the receiver argument from the domain provided. 310 func (p *gtm) DeleteProperty(ctx context.Context, property *Property, domainName string) (*ResponseStatus, error) { 311 312 logger := p.Log(ctx) 313 logger.Debug("DeleteProperty") 314 315 if err := property.Validate(); err != nil { 316 logger.Errorf("Property validation failed. %w", err) 317 return nil, fmt.Errorf("Property validation failed. %w", err) 318 } 319 320 delURL := fmt.Sprintf("/config-gtm/v1/domains/%s/properties/%s", domainName, property.Name) 321 req, err := http.NewRequestWithContext(ctx, http.MethodDelete, delURL, nil) 322 if err != nil { 323 return nil, fmt.Errorf("failed to create Property request: %w", err) 324 } 325 326 var presp ResponseBody 327 setVersionHeader(req, schemaVersion) 328 resp, err := p.Exec(req, &presp) 329 if err != nil { 330 return nil, fmt.Errorf("Property request failed: %w", err) 331 } 332 333 if resp.StatusCode != http.StatusOK { 334 return nil, p.Error(resp) 335 } 336 337 return presp.Status, nil 338 }