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