github.com/akamai/AkamaiOPEN-edgegrid-golang/v5@v5.0.0/pkg/gtm/resource.go (about) 1 package gtm 2 3 import ( 4 "context" 5 "fmt" 6 "net/http" 7 ) 8 9 // 10 // Handle Operations on gtm resources 11 // Based on 1.4 schema 12 // 13 14 // Resources contains operations available on a Resource resource. 15 type Resources interface { 16 // NewResourceInstance instantiates a new ResourceInstance. 17 NewResourceInstance(context.Context, *Resource, int) *ResourceInstance 18 // NewResource creates a new Resource object. 19 NewResource(context.Context, string) *Resource 20 // ListResources retreieves all Resources 21 // 22 // See: https://techdocs.akamai.com/gtm/reference/get-resources 23 ListResources(context.Context, string) ([]*Resource, error) 24 // GetResource retrieves a Resource with the given name. 25 // 26 // See: https://techdocs.akamai.com/gtm/reference/get-resource 27 GetResource(context.Context, string, string) (*Resource, error) 28 // CreateResource creates the datacenter identified by the receiver argument in the specified domain. 29 // 30 // See: https://techdocs.akamai.com/gtm/reference/put-resource 31 CreateResource(context.Context, *Resource, string) (*ResourceResponse, error) 32 // DeleteResource deletes the datacenter identified by the receiver argument from the domain specified. 33 // 34 // See: https://techdocs.akamai.com/gtm/reference/delete-resource 35 DeleteResource(context.Context, *Resource, string) (*ResponseStatus, error) 36 // UpdateResource updates the datacenter identified in the receiver argument in the provided domain. 37 // 38 // See: https://techdocs.akamai.com/gtm/reference/put-resource 39 UpdateResource(context.Context, *Resource, string) (*ResponseStatus, error) 40 } 41 42 // ResourceInstance contains information about the resources that constrain the properties within the data center 43 type ResourceInstance struct { 44 DatacenterId int `json:"datacenterId"` 45 UseDefaultLoadObject bool `json:"useDefaultLoadObject"` 46 LoadObject 47 } 48 49 // Resource represents a GTM resource 50 type Resource struct { 51 Type string `json:"type"` 52 HostHeader string `json:"hostHeader,omitempty"` 53 LeastSquaresDecay float64 `json:"leastSquaresDecay,omitempty"` 54 Description string `json:"description,omitempty"` 55 LeaderString string `json:"leaderString,omitempty"` 56 ConstrainedProperty string `json:"constrainedProperty,omitempty"` 57 ResourceInstances []*ResourceInstance `json:"resourceInstances,omitempty"` 58 AggregationType string `json:"aggregationType,omitempty"` 59 Links []*Link `json:"links,omitempty"` 60 LoadImbalancePercentage float64 `json:"loadImbalancePercentage,omitempty"` 61 UpperBound int `json:"upperBound,omitempty"` 62 Name string `json:"name"` 63 MaxUMultiplicativeIncrement float64 `json:"maxUMultiplicativeIncrement,omitempty"` 64 DecayRate float64 `json:"decayRate,omitempty"` 65 } 66 67 // ResourceList is the structure returned by List Resources 68 type ResourceList struct { 69 ResourceItems []*Resource `json:"items"` 70 } 71 72 // Validate validates Resource 73 func (rsrc *Resource) Validate() error { 74 75 if len(rsrc.Name) < 1 { 76 return fmt.Errorf("Resource is missing Name") 77 } 78 if len(rsrc.Type) < 1 { 79 return fmt.Errorf("Resource is missing Type") 80 } 81 82 return nil 83 } 84 85 func (p *gtm) NewResourceInstance(ctx context.Context, _ *Resource, dcID int) *ResourceInstance { 86 87 logger := p.Log(ctx) 88 logger.Debug("NewResourceInstance") 89 90 return &ResourceInstance{DatacenterId: dcID} 91 92 } 93 94 func (p *gtm) NewResource(ctx context.Context, name string) *Resource { 95 96 logger := p.Log(ctx) 97 logger.Debug("NewResource") 98 99 resource := &Resource{Name: name} 100 return resource 101 } 102 103 func (p *gtm) ListResources(ctx context.Context, domainName string) ([]*Resource, error) { 104 105 logger := p.Log(ctx) 106 logger.Debug("ListResources") 107 108 var rsrcs ResourceList 109 getURL := fmt.Sprintf("/config-gtm/v1/domains/%s/resources", domainName) 110 req, err := http.NewRequestWithContext(ctx, http.MethodGet, getURL, nil) 111 if err != nil { 112 return nil, fmt.Errorf("failed to create ListResources request: %w", err) 113 } 114 setVersionHeader(req, schemaVersion) 115 resp, err := p.Exec(req, &rsrcs) 116 if err != nil { 117 return nil, fmt.Errorf("ListResources request failed: %w", err) 118 } 119 120 if resp.StatusCode != http.StatusOK { 121 return nil, p.Error(resp) 122 } 123 124 return rsrcs.ResourceItems, nil 125 } 126 127 func (p *gtm) GetResource(ctx context.Context, name, domainName string) (*Resource, error) { 128 129 logger := p.Log(ctx) 130 logger.Debug("GetResource") 131 132 var rsc Resource 133 getURL := fmt.Sprintf("/config-gtm/v1/domains/%s/resources/%s", domainName, name) 134 req, err := http.NewRequestWithContext(ctx, http.MethodGet, getURL, nil) 135 if err != nil { 136 return nil, fmt.Errorf("failed to create GetResource request: %w", err) 137 } 138 setVersionHeader(req, schemaVersion) 139 resp, err := p.Exec(req, &rsc) 140 if err != nil { 141 return nil, fmt.Errorf("GetResource request failed: %w", err) 142 } 143 144 if resp.StatusCode != http.StatusOK { 145 return nil, p.Error(resp) 146 } 147 148 return &rsc, nil 149 } 150 151 func (p *gtm) CreateResource(ctx context.Context, rsrc *Resource, domainName string) (*ResourceResponse, error) { 152 153 logger := p.Log(ctx) 154 logger.Debug("CreateResource") 155 156 // Use common code. Any specific validation needed? 157 return rsrc.save(ctx, p, domainName) 158 159 } 160 161 func (p *gtm) UpdateResource(ctx context.Context, rsrc *Resource, domainName string) (*ResponseStatus, error) { 162 163 logger := p.Log(ctx) 164 logger.Debug("UpdateResource") 165 166 // common code 167 stat, err := rsrc.save(ctx, p, domainName) 168 if err != nil { 169 return nil, err 170 } 171 return stat.Status, err 172 173 } 174 175 // save is a function that saves Resource in given domain. Common path for Create and Update. 176 func (rsrc *Resource) save(ctx context.Context, p *gtm, domainName string) (*ResourceResponse, error) { 177 178 if err := rsrc.Validate(); err != nil { 179 return nil, fmt.Errorf("Resource validation failed. %w", err) 180 } 181 182 putURL := fmt.Sprintf("/config-gtm/v1/domains/%s/resources/%s", domainName, rsrc.Name) 183 req, err := http.NewRequestWithContext(ctx, http.MethodPut, putURL, nil) 184 if err != nil { 185 return nil, fmt.Errorf("failed to create Resource request: %w", err) 186 } 187 188 var rscresp ResourceResponse 189 setVersionHeader(req, schemaVersion) 190 resp, err := p.Exec(req, &rscresp, rsrc) 191 if err != nil { 192 return nil, fmt.Errorf("Resource request failed: %w", err) 193 } 194 195 if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated { 196 return nil, p.Error(resp) 197 } 198 199 return &rscresp, nil 200 201 } 202 203 func (p *gtm) DeleteResource(ctx context.Context, rsrc *Resource, domainName string) (*ResponseStatus, error) { 204 205 logger := p.Log(ctx) 206 logger.Debug("DeleteResource") 207 208 if err := rsrc.Validate(); err != nil { 209 logger.Errorf("Resource validation failed. %w", err) 210 return nil, fmt.Errorf("Resource validation failed. %w", err) 211 } 212 213 delURL := fmt.Sprintf("/config-gtm/v1/domains/%s/resources/%s", domainName, rsrc.Name) 214 req, err := http.NewRequestWithContext(ctx, http.MethodDelete, delURL, nil) 215 if err != nil { 216 return nil, fmt.Errorf("failed to create Delete request: %w", err) 217 } 218 219 var rscresp ResponseBody 220 setVersionHeader(req, schemaVersion) 221 resp, err := p.Exec(req, &rscresp) 222 if err != nil { 223 return nil, fmt.Errorf("Resource request failed: %w", err) 224 } 225 226 if resp.StatusCode != http.StatusOK { 227 return nil, p.Error(resp) 228 } 229 230 return rscresp.Status, nil 231 232 }