├── jsonhooks-v1 ├── README.md ├── errors.go ├── jsonhooks.go └── jsonhooks_test.go ├── api-endpoints-v2 ├── links.go ├── import_results.go ├── acg_pair.go ├── problems.go ├── api_privacy_settings.go ├── gzip_settings.go ├── cors_settings.go ├── category.go ├── methods.go ├── service.go ├── service_test.go ├── jwt_settings.go ├── parameters.go ├── activations.go ├── cache_settings.go ├── resources.go └── versions.go ├── client-v1 ├── README.md ├── api_test.go ├── api.go ├── client_test.go ├── errors.go └── client.go ├── edgegrid ├── README.md ├── profilecache.go ├── errors.go ├── signer_test.go ├── log.go └── config.go ├── testdata ├── edgerc_that_doesnt_parse ├── nodefault_edgerc └── sample_edgerc ├── configdns-v1 ├── README.md ├── service.go ├── errors.go └── record_test.go ├── configdns-v2 ├── README.md ├── service.go ├── authorities.go ├── zone_test.go ├── recordsets_test.go ├── errors.go └── recordsets.go ├── configgtm-v1_3 ├── README.md ├── service.go ├── errors.go ├── common.go └── asmap.go ├── configgtm-v1_4 ├── README.md ├── service.go ├── errors.go ├── common.go └── asmap.go ├── papi-v1 ├── README.md ├── init.go ├── errors.go ├── search.go ├── client_settings.go ├── ruleformats.go ├── service.go ├── customoverrides_test.go ├── products.go ├── custombehaviors_test.go ├── contracts.go ├── hostnames.go ├── custombehaviors.go ├── customoverrides.go └── available.go ├── reportsgtm-v1 ├── README.md ├── service_test.go ├── service.go ├── datacenter.go ├── datacenter_test.go ├── util.go └── property.go ├── .gitignore ├── cps-v2 ├── certificate_settings_test.go ├── service.go ├── certificate_settings.go └── enrollments.go ├── ccu-v3 ├── service.go ├── service_test.go └── purge.go ├── apikey-manager-v1 ├── service.go ├── keys.go └── collections.go ├── go.mod ├── examples ├── edgegrid_without_configfile │ └── edgegrid_without_configfile.go ├── edgegrid │ └── edgegrid.go └── client │ └── client.go ├── .travis.yml ├── CHANGELOG.md └── go.sum /jsonhooks-v1/README.md: -------------------------------------------------------------------------------- 1 | # Akamai JSONHooks -------------------------------------------------------------------------------- /jsonhooks-v1/errors.go: -------------------------------------------------------------------------------- 1 | package jsonhooks 2 | -------------------------------------------------------------------------------- /api-endpoints-v2/links.go: -------------------------------------------------------------------------------- 1 | package apiendpoints 2 | 3 | type Links []struct { 4 | Rel string `json:"rel"` 5 | Href string `json:"href"` 6 | } 7 | -------------------------------------------------------------------------------- /client-v1/README.md: -------------------------------------------------------------------------------- 1 | # Akamai Client 2 | 3 | A golang package which helps facilitate making HTTP requests to [Akamai OPEN APIs](https://developer.akamai.com) -------------------------------------------------------------------------------- /edgegrid/README.md: -------------------------------------------------------------------------------- 1 | # Akamai Edgegrid 2 | A golang package which facilitates authenticating and signing requests made to [Akamai OPEN APIs](https://developer.akamai.com). -------------------------------------------------------------------------------- /testdata/edgerc_that_doesnt_parse: -------------------------------------------------------------------------------- 1 | [default] 2 | client_token = xxxx-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx 3 | access_token = xxxx-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx 4 | max_body = 131072 5 | -------------------------------------------------------------------------------- /configdns-v1/README.md: -------------------------------------------------------------------------------- 1 | # Akamai Config DNS (Zone Record Management) 2 | A golang package that talks to the [Akamai OPEN Config DNS API](https://developer.akamai.com/api/luna/config-dns/overview.html). -------------------------------------------------------------------------------- /configdns-v2/README.md: -------------------------------------------------------------------------------- 1 | # Akamai Config DNS (Zone Record Management) 2 | A golang package that talks to the [Akamai OPEN Config DNS API](https://developer.akamai.com/api/luna/config-dns/overview.html). -------------------------------------------------------------------------------- /api-endpoints-v2/import_results.go: -------------------------------------------------------------------------------- 1 | package apiendpoints 2 | 3 | type ImportResult struct { 4 | APIEndpointDetails Endpoint `json:"apiEndpointDetails"` 5 | Problems Problems `json:"problems"` 6 | } 7 | -------------------------------------------------------------------------------- /configgtm-v1_3/README.md: -------------------------------------------------------------------------------- 1 | # Akamai Config GTM (Global Traffic Management) 2 | A golang package that talks to the [Akamai OPEN Config GTM API](https://developer.akamai.com/api/luna/config-gtm/overview.html). 3 | -------------------------------------------------------------------------------- /configgtm-v1_4/README.md: -------------------------------------------------------------------------------- 1 | # Akamai Config GTM (Global Traffic Management) 2 | A golang package that talks to the [Akamai OPEN Config GTM API](https://developer.akamai.com/api/luna/config-gtm/overview.html). 3 | -------------------------------------------------------------------------------- /papi-v1/README.md: -------------------------------------------------------------------------------- 1 | # Akamai Property Manager API (PAPI) 2 | A golang package which facilitates making requests to the [Akamai OPEN Property Manager API](https://developer.akamai.com/api/luna/papi/overview.html). -------------------------------------------------------------------------------- /reportsgtm-v1/README.md: -------------------------------------------------------------------------------- 1 | # Akamai GTM Reports (Global Traffic Management) 2 | A golang package that talks to the [Akamai OPEN GTM Reporting API](https://developer.akamai.com/api/web_performance/global_traffic_management_reporting/v1.html#overview). 3 | -------------------------------------------------------------------------------- /api-endpoints-v2/acg_pair.go: -------------------------------------------------------------------------------- 1 | package apiendpoints 2 | 3 | type AcgPair []struct { 4 | DisplayName string `json:"displayName"` 5 | AcgID string `json:"acgId"` 6 | GroupID int `json:"groupId"` 7 | ContractID string `json:"contractId"` 8 | } 9 | -------------------------------------------------------------------------------- /testdata/nodefault_edgerc: -------------------------------------------------------------------------------- 1 | [nodefault] 2 | host = xxxx-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net/ 3 | client_token = xxxx-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx 4 | client_secret = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= 5 | access_token = xxxx-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx 6 | max_body = 131072 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # testing and custom build code 2 | *.log 3 | 4 | # local files 5 | .DS_Store 6 | /dist 7 | 8 | # vscode 9 | .vscode/ 10 | _debug_bin 11 | 12 | # eclipse 13 | .classpath 14 | .project 15 | .settings 16 | 17 | # IntelliJ 18 | /.idea/ 19 | *.ipr 20 | *.iws 21 | *.iml 22 | 23 | # go dependencies 24 | vendor/ -------------------------------------------------------------------------------- /papi-v1/init.go: -------------------------------------------------------------------------------- 1 | // Package papi provides a simple wrapper for the Akamai Property Manager API 2 | package papi 3 | 4 | import "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 5 | 6 | // Init sets the PAPI edgegrid Config 7 | func Init(config edgegrid.Config) { 8 | 9 | Config = config 10 | edgegrid.SetupLogging() 11 | } 12 | -------------------------------------------------------------------------------- /cps-v2/certificate_settings_test.go: -------------------------------------------------------------------------------- 1 | package cps 2 | 3 | import ( 4 | "testing" 5 | 6 | //cps "github.com/akamai/AkamaiOPEN-edgegrid-golang/cps-v2" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestSHAConversion(t *testing.T) { 11 | assert.NotEqual(t, "dosty", "everts") 12 | assert.Equal(t, SHA256, SHA("SHA-256")) 13 | } 14 | -------------------------------------------------------------------------------- /api-endpoints-v2/problems.go: -------------------------------------------------------------------------------- 1 | package apiendpoints 2 | 3 | type Problems []*Problem 4 | 5 | type Problem struct { 6 | Detail string `json:"detail"` 7 | Errors Problems `json:"errors"` 8 | Instance string `json:"instance"` 9 | Status int `json:"status"` 10 | Title string `json:"title"` 11 | Type string `json:"type"` 12 | } 13 | -------------------------------------------------------------------------------- /api-endpoints-v2/api_privacy_settings.go: -------------------------------------------------------------------------------- 1 | package apiendpoints 2 | 3 | type APIPrivacySettings struct { 4 | Resources map[int]APIPrivacyResource `json:"resources"` 5 | Public bool `json:"public"` 6 | } 7 | 8 | type APIPrivacyResource struct { 9 | ResourceSettings 10 | Notes string `json:"notes"` 11 | Public bool `json:"public"` 12 | } 13 | -------------------------------------------------------------------------------- /ccu-v3/service.go: -------------------------------------------------------------------------------- 1 | package ccu 2 | 3 | import ( 4 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 5 | ) 6 | 7 | var ( 8 | // Config contains the Akamai OPEN Edgegrid API credentials 9 | // for automatic signing of requests 10 | Config edgegrid.Config 11 | ) 12 | 13 | // Init sets the CCU edgegrid Config 14 | func Init(config edgegrid.Config) { 15 | Config = config 16 | } 17 | -------------------------------------------------------------------------------- /configdns-v1/service.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import ( 4 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 5 | ) 6 | 7 | var ( 8 | // Config contains the Akamai OPEN Edgegrid API credentials 9 | // for automatic signing of requests 10 | Config edgegrid.Config 11 | ) 12 | 13 | // Init sets the FastDNS edgegrid Config 14 | func Init(config edgegrid.Config) { 15 | Config = config 16 | } 17 | -------------------------------------------------------------------------------- /apikey-manager-v1/service.go: -------------------------------------------------------------------------------- 1 | package apikeymanager 2 | 3 | import ( 4 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 5 | ) 6 | 7 | var ( 8 | // Config contains the Akamai OPEN Edgegrid API credentials 9 | // for automatic signing of requests 10 | Config edgegrid.Config 11 | ) 12 | 13 | // Init sets the edgegrid Config 14 | func Init(config edgegrid.Config) { 15 | Config = config 16 | } 17 | -------------------------------------------------------------------------------- /configdns-v2/service.go: -------------------------------------------------------------------------------- 1 | package dnsv2 2 | 3 | import ( 4 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 5 | ) 6 | 7 | var ( 8 | // Config contains the Akamai OPEN Edgegrid API credentials 9 | // for automatic signing of requests 10 | Config edgegrid.Config 11 | ) 12 | 13 | // Init sets the DNSv2 edgegrid Config 14 | func Init(config edgegrid.Config) { 15 | Config = config 16 | edgegrid.SetupLogging() 17 | 18 | } 19 | -------------------------------------------------------------------------------- /api-endpoints-v2/gzip_settings.go: -------------------------------------------------------------------------------- 1 | package apiendpoints 2 | 3 | type GzipSettings struct { 4 | CompressResponse CompressResponseValue `json:"compressResponse"` 5 | } 6 | 7 | type CompressResponseValue string 8 | 9 | const ( 10 | CompressResponseAlways CompressResponseValue = "ALWAYS" 11 | CompressResponseNever CompressResponseValue = "NEVER" 12 | CompressResponseSameAsOrigin CompressResponseValue = "SAME_AS_ORIGIN" 13 | ) 14 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/akamai/AkamaiOPEN-edgegrid-golang 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/google/go-querystring v1.0.0 7 | github.com/google/uuid v1.1.1 8 | github.com/mitchellh/go-homedir v1.1.0 9 | github.com/patrickmn/go-cache v2.1.0+incompatible 10 | github.com/sirupsen/logrus v1.4.2 11 | github.com/smartystreets/goconvey v1.6.4 // indirect 12 | github.com/stretchr/testify v1.4.0 13 | github.com/xeipuuv/gojsonschema v1.2.0 14 | gopkg.in/h2non/gock.v1 v1.0.15 15 | gopkg.in/ini.v1 v1.51.1 16 | ) 17 | -------------------------------------------------------------------------------- /edgegrid/profilecache.go: -------------------------------------------------------------------------------- 1 | package edgegrid 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/patrickmn/go-cache" 7 | gocache "github.com/patrickmn/go-cache" 8 | ) 9 | 10 | // Config struct provides all the necessary fields to 11 | // create authorization header, debug is optional 12 | type ( 13 | profileCache gocache.Cache 14 | ) 15 | 16 | // Init initializes cache 17 | // 18 | 19 | // See: InitCache() 20 | func InitCache() (gocache.Cache, error) { 21 | cache := cache.New(5*time.Minute, 10*time.Minute) 22 | return *cache, nil 23 | } 24 | -------------------------------------------------------------------------------- /api-endpoints-v2/cors_settings.go: -------------------------------------------------------------------------------- 1 | package apiendpoints 2 | 3 | type CORSSetings struct { 4 | Enabled bool `json:"enabled"` 5 | AllowedOrigins []string `json:"allowedOrigins,omitempty"` 6 | AllowedHeaders []string `json:"allowedHeaders,omitempty"` 7 | AllowedMethods []MethodValue `json:"allowedMethods,omitempty"` 8 | AllowCredentials bool `json:"allowCredentials,omitempty"` 9 | ExposedHeaders []string `json:"exposedHeaders,omitempty"` 10 | PreflightMaxAge int `json:"preflightMaxAge,omitempty"` 11 | } 12 | -------------------------------------------------------------------------------- /reportsgtm-v1/service_test.go: -------------------------------------------------------------------------------- 1 | package reportsgtm 2 | 3 | import ( 4 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 5 | ) 6 | 7 | var ( 8 | config = edgegrid.Config{ 9 | Host: "akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/", 10 | AccessToken: "akab-access-token-xxx-xxxxxxxxxxxxxxxx", 11 | ClientToken: "akab-client-token-xxx-xxxxxxxxxxxxxxxx", 12 | ClientSecret: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=", 13 | MaxBody: 2048, 14 | Debug: false, 15 | } 16 | ) 17 | 18 | var gtmTestDomain = "gtmtest.akadns.net" 19 | -------------------------------------------------------------------------------- /api-endpoints-v2/category.go: -------------------------------------------------------------------------------- 1 | package apiendpoints 2 | 3 | type Category struct { 4 | APICategoryID int `json:"apiCategoryId,omitempty"` 5 | APICategoryName string `json:"apiCategoryName"` 6 | APICategoryDescription string `json:"apiCategoryDescription"` 7 | Link string `json:"link"` 8 | LockVersion int `json:"lockVersion"` 9 | CreatedBy string `json:"createdBy,omitempty"` 10 | CreateDate string `json:"createDate,omitempty"` 11 | UpdatedBy string `json:"updatedBy,omitempty"` 12 | UpdateDate string `json:"updateDate,omitempty"` 13 | } 14 | -------------------------------------------------------------------------------- /papi-v1/errors.go: -------------------------------------------------------------------------------- 1 | package papi 2 | 3 | import "errors" 4 | 5 | // Error constants 6 | const ( 7 | ErrInvalidPath = iota 8 | ErrCriteriaNotFound 9 | ErrBehaviorNotFound 10 | ErrVariableNotFound 11 | ErrRuleNotFound 12 | ErrInvalidRules 13 | ) 14 | 15 | var ( 16 | ErrorMap = map[int]error{ 17 | ErrInvalidPath: errors.New("Invalid Path"), 18 | ErrCriteriaNotFound: errors.New("Criteria not found"), 19 | ErrBehaviorNotFound: errors.New("Behavior not found"), 20 | ErrVariableNotFound: errors.New("Variable not found"), 21 | ErrRuleNotFound: errors.New("Rule not found"), 22 | ErrInvalidRules: errors.New("Rule validation failed. See papi.Rules.Errors for details"), 23 | } 24 | ) 25 | -------------------------------------------------------------------------------- /api-endpoints-v2/methods.go: -------------------------------------------------------------------------------- 1 | package apiendpoints 2 | 3 | type Methods []Method 4 | 5 | type Method struct { 6 | APIResourceMethodID int `json:"apiResourceMethodId"` 7 | APIResourceMethod MethodValue `json:"apiResourceMethod"` 8 | APIResourceMethodLogicID int `json:"apiResourceMethodLogicId"` 9 | APIParameters []Parameters `json:"apiParameters"` 10 | } 11 | 12 | type MethodValue string 13 | 14 | const ( 15 | MethodGet MethodValue = "get" 16 | MethodPost MethodValue = "post" 17 | MethodPut MethodValue = "put" 18 | MethodDelete MethodValue = "delete" 19 | MethodHead MethodValue = "head" 20 | MethodPatch MethodValue = "patch" 21 | MethodOptions MethodValue = "options" 22 | ) 23 | -------------------------------------------------------------------------------- /edgegrid/errors.go: -------------------------------------------------------------------------------- 1 | package edgegrid 2 | 3 | // Error constants 4 | const ( 5 | ErrUUIDGenerateFailed = 500 6 | ErrHomeDirNotFound = 501 7 | ErrConfigFile = 502 8 | ErrConfigFileSection = 503 9 | ErrConfigMissingOptions = 504 10 | ErrMissingEnvVariables = 505 11 | ) 12 | 13 | var ( 14 | errorMap = map[int]string{ 15 | ErrUUIDGenerateFailed: "Generate UUID failed: %s", 16 | ErrHomeDirNotFound: "Fatal could not find home dir from user: %s", 17 | ErrConfigFile: "Fatal error edgegrid file: %s", 18 | ErrConfigFileSection: "Could not map section: %s", 19 | ErrConfigMissingOptions: "Fatal missing required options: %s", 20 | ErrMissingEnvVariables: "Fatal missing required environment variables: %s", 21 | } 22 | ) 23 | -------------------------------------------------------------------------------- /configgtm-v1_3/service.go: -------------------------------------------------------------------------------- 1 | package configgtm 2 | 3 | import ( 4 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 5 | "net/http" 6 | ) 7 | 8 | var ( 9 | // Config contains the Akamai OPEN Edgegrid API credentials 10 | // for automatic signing of requests 11 | Config edgegrid.Config 12 | ) 13 | 14 | // Init sets the GTM edgegrid Config 15 | func Init(config edgegrid.Config) { 16 | 17 | Config = config 18 | edgegrid.SetupLogging() 19 | 20 | } 21 | 22 | // Utility func to print http req 23 | func printHttpRequest(req *http.Request, body bool) { 24 | 25 | edgegrid.PrintHttpRequest(req, body) 26 | 27 | } 28 | 29 | // Utility func to print http response 30 | func printHttpResponse(res *http.Response, body bool) { 31 | 32 | edgegrid.PrintHttpResponse(res, body) 33 | 34 | } 35 | -------------------------------------------------------------------------------- /configgtm-v1_4/service.go: -------------------------------------------------------------------------------- 1 | package configgtm 2 | 3 | import ( 4 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 5 | "net/http" 6 | ) 7 | 8 | var ( 9 | // Config contains the Akamai OPEN Edgegrid API credentials 10 | // for automatic signing of requests 11 | Config edgegrid.Config 12 | ) 13 | 14 | // Init sets the GTM edgegrid Config 15 | func Init(config edgegrid.Config) { 16 | 17 | Config = config 18 | edgegrid.SetupLogging() 19 | 20 | } 21 | 22 | // Utility func to print http req 23 | func printHttpRequest(req *http.Request, body bool) { 24 | 25 | edgegrid.PrintHttpRequest(req, body) 26 | 27 | } 28 | 29 | // Utility func to print http response 30 | func printHttpResponse(res *http.Response, body bool) { 31 | 32 | edgegrid.PrintHttpResponse(res, body) 33 | 34 | } 35 | -------------------------------------------------------------------------------- /reportsgtm-v1/service.go: -------------------------------------------------------------------------------- 1 | package reportsgtm 2 | 3 | import ( 4 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 5 | "net/http" 6 | ) 7 | 8 | var ( 9 | // Config contains the Akamai OPEN Edgegrid API credentials 10 | // for automatic signing of requests 11 | Config edgegrid.Config 12 | ) 13 | 14 | // Init sets the GTM edgegrid Config 15 | func Init(config edgegrid.Config) { 16 | 17 | Config = config 18 | edgegrid.SetupLogging() 19 | 20 | } 21 | 22 | // Utility func to print http req 23 | func printHttpRequest(req *http.Request, body bool) { 24 | 25 | edgegrid.PrintHttpRequest(req, body) 26 | 27 | } 28 | 29 | // Utility func to print http response 30 | func printHttpResponse(res *http.Response, body bool) { 31 | 32 | edgegrid.PrintHttpResponse(res, body) 33 | 34 | } 35 | -------------------------------------------------------------------------------- /client-v1/api_test.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/jsonhooks-v1" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | type Test struct { 11 | Resource 12 | Foo string `json:"foo"` 13 | } 14 | 15 | func (test *Test) PreMarshalJSON() error { 16 | test.Foo = "bat" 17 | 18 | return nil 19 | } 20 | 21 | func TestResourceUnmarshal(t *testing.T) { 22 | body := []byte(`{"foo":"bar"}`) 23 | 24 | test := &Test{} 25 | err := jsonhooks.Unmarshal(body, test) 26 | 27 | assert.NoError(t, err) 28 | assert.True(t, <-test.Complete) 29 | } 30 | 31 | func TestResourceMarshal(t *testing.T) { 32 | test := &Test{Foo: "bar"} 33 | 34 | body, err := jsonhooks.Marshal(test) 35 | 36 | assert.NoError(t, err) 37 | assert.Equal(t, []byte(`{"foo":"bat"}`), body) 38 | } 39 | -------------------------------------------------------------------------------- /examples/edgegrid_without_configfile/edgegrid_without_configfile.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 6 | "io/ioutil" 7 | "net/http" 8 | ) 9 | 10 | func main() { 11 | client := http.Client{} 12 | config := edgegrid.Config{ 13 | Host: "xxxxxx.luna.akamaiapis.net", 14 | ClientToken: "xxxx-xxxxxxxxxxx-xxxxxxxxxxx", 15 | ClientSecret: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 16 | AccessToken: "xxxx-xxxxxxxxxxx-xxxxxxxxxxx", 17 | MaxBody: 1024, 18 | HeaderToSign: []string{ 19 | "X-Test1", 20 | "X-Test2", 21 | "X-Test3", 22 | }, 23 | Debug: false, 24 | } 25 | 26 | req, _ := http.NewRequest("GET", fmt.Sprintf("https://%s/siteshield/v1/maps", config.Host), nil) 27 | req = edgegrid.AddRequestHeader(config, req) 28 | resp, _ := client.Do(req) 29 | byt, _ := ioutil.ReadAll(resp.Body) 30 | fmt.Println(string(byt)) 31 | } 32 | -------------------------------------------------------------------------------- /api-endpoints-v2/service.go: -------------------------------------------------------------------------------- 1 | package apiendpoints 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 7 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 8 | ) 9 | 10 | var ( 11 | // Config contains the Akamai OPEN Edgegrid API credentials 12 | // for automatic signing of requests 13 | Config edgegrid.Config 14 | ) 15 | 16 | // Init sets the CCU edgegrid Config 17 | func Init(config edgegrid.Config) { 18 | Config = config 19 | } 20 | 21 | func call(req *http.Request, err error) (*Endpoint, error) { 22 | if err != nil { 23 | return nil, err 24 | } 25 | 26 | res, err := client.Do(Config, req) 27 | 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | if client.IsError(res) { 33 | return nil, client.NewAPIError(res) 34 | } 35 | 36 | rep := &Endpoint{} 37 | if err = client.BodyJSON(res, rep); err != nil { 38 | return nil, err 39 | } 40 | 41 | return rep, nil 42 | } 43 | -------------------------------------------------------------------------------- /ccu-v3/service_test.go: -------------------------------------------------------------------------------- 1 | package ccu 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | var ( 11 | config = edgegrid.Config{ 12 | Host: "akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/", 13 | AccessToken: "akab-access-token-xxx-xxxxxxxxxxxxxxxx", 14 | ClientToken: "akab-client-token-xxx-xxxxxxxxxxxxxxxx", 15 | ClientSecret: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=", 16 | MaxBody: 2048, 17 | Debug: false, 18 | } 19 | ) 20 | 21 | func TestInit(t *testing.T) { 22 | Init(config) 23 | 24 | assert.Equal(t, config.Host, Config.Host) 25 | assert.Equal(t, config.AccessToken, Config.AccessToken) 26 | assert.Equal(t, config.ClientToken, Config.ClientToken) 27 | assert.Equal(t, config.ClientSecret, Config.ClientSecret) 28 | assert.Equal(t, config.MaxBody, Config.MaxBody) 29 | assert.Equal(t, config.Debug, Config.Debug) 30 | } 31 | -------------------------------------------------------------------------------- /api-endpoints-v2/service_test.go: -------------------------------------------------------------------------------- 1 | package apiendpoints 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | var ( 11 | config = edgegrid.Config{ 12 | Host: "akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/", 13 | AccessToken: "akab-access-token-xxx-xxxxxxxxxxxxxxxx", 14 | ClientToken: "akab-client-token-xxx-xxxxxxxxxxxxxxxx", 15 | ClientSecret: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=", 16 | MaxBody: 2048, 17 | Debug: false, 18 | } 19 | ) 20 | 21 | func TestInit(t *testing.T) { 22 | Init(config) 23 | 24 | assert.Equal(t, config.Host, Config.Host) 25 | assert.Equal(t, config.AccessToken, Config.AccessToken) 26 | assert.Equal(t, config.ClientToken, Config.ClientToken) 27 | assert.Equal(t, config.ClientSecret, Config.ClientSecret) 28 | assert.Equal(t, config.MaxBody, Config.MaxBody) 29 | assert.Equal(t, config.Debug, Config.Debug) 30 | } 31 | -------------------------------------------------------------------------------- /cps-v2/service.go: -------------------------------------------------------------------------------- 1 | package cps 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "log" 7 | "net/http" 8 | 9 | client "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 10 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 11 | ) 12 | 13 | var ( 14 | // Config contains the Akamai OPEN Edgegrid API credentials 15 | // for automatic signing of requests 16 | Config edgegrid.Config 17 | ) 18 | 19 | // Init sets the CPS edgegrid Config 20 | func Init(config edgegrid.Config) { 21 | Config = config 22 | } 23 | 24 | func newRequest(method, urlStr string, body interface{}) (*http.Request, error) { 25 | buf := new(bytes.Buffer) 26 | err := json.NewEncoder(buf).Encode(body) 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | log.Printf("[DEBUG] newRequest, buf: %s", string(buf.Bytes())) 32 | 33 | req, err := client.NewRequest(Config, method, urlStr, buf) 34 | if err != nil { 35 | return nil, err 36 | } 37 | req.Header.Add("Content-Type", "application/vnd.akamai.cps.enrollment.v7+json") 38 | req.Header.Add("Accept", "application/vnd.akamai.cps.enrollment-status.v1+json") 39 | 40 | return req, nil 41 | } 42 | -------------------------------------------------------------------------------- /testdata/sample_edgerc: -------------------------------------------------------------------------------- 1 | [default] 2 | host = xxxx-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net/ 3 | client_token = xxxx-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx 4 | client_secret = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= 5 | access_token = xxxx-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx 6 | max_body = 131072 7 | [test] 8 | host = test-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net/ 9 | client_token = test-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx 10 | client_secret = testxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= 11 | access_token = test-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx 12 | max_body = 131072 13 | [broken] 14 | host = "https://xxxx-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net/" 15 | client_token = xxxx-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx 16 | client_secret = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= 17 | access_token = xxxx-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx 18 | [dashes] 19 | host = xxxx-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net/ 20 | client-token = xxxx-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx 21 | client-secret = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= 22 | access-token = xxxx-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx 23 | max-body = 131072 24 | -------------------------------------------------------------------------------- /client-v1/api.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // Resource is the "base" type for all API resources 8 | type Resource struct { 9 | Complete chan bool `json:"-"` 10 | } 11 | 12 | // Init initializes the Complete channel, if it is necessary 13 | // need to create a resource specific Init(), make sure to 14 | // initialize the channel. 15 | func (resource *Resource) Init() { 16 | resource.Complete = make(chan bool, 1) 17 | } 18 | 19 | // PostUnmarshalJSON is a default implementation of the 20 | // PostUnmarshalJSON hook that simply calls Init() and 21 | // sends true to the Complete channel. This is overridden 22 | // in many resources, in particular those that represent 23 | // collections, and have to initialize sub-resources also. 24 | func (resource *Resource) PostUnmarshalJSON() error { 25 | resource.Init() 26 | resource.Complete <- true 27 | return nil 28 | } 29 | 30 | // GetJSON returns the raw (indented) JSON (as []bytes) 31 | func (resource *Resource) GetJSON() ([]byte, error) { 32 | return json.MarshalIndent(resource, "", " ") 33 | } 34 | 35 | // JSONBody is a generic struct for temporary JSON unmarshalling. 36 | type JSONBody map[string]interface{} 37 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | # Fix patching for forks 5 | go_import_path: github.com/akamai/AkamaiOPEN-edgegrid-golang 6 | 7 | cache: 8 | directories: 9 | - $GOPATH/pkg/mod 10 | 11 | matrix: 12 | fast_finish: true 13 | include: 14 | - go: 1.12.x 15 | - go: 1.13.x 16 | - go: 1.x 17 | - go: tip 18 | allow_failures: 19 | - go: tip 20 | 21 | env: 22 | global: 23 | - GO111MODULE=on 24 | 25 | install: 26 | - go mod tidy 27 | - git diff --exit-code go.mod 28 | - git diff --exit-code go.sum 29 | - go mod download 30 | 31 | script: 32 | - go test -v ./... 33 | 34 | notifications: 35 | slack: 36 | secure: sf5CrgPZ2UjTmGFg1hbSdEB3GXyBybeoZQDOI/pk1ywId4mjN1HgAFooDaZx9Qn+orhdQny3jMcdx1qyLe9YtV7WhIRGRQWgJiZ7H+6YRCWYNnSopsSDJ91Q/PaQrgsPSIHL+vfSkyW9iDXrT09SK0IOlWHTrrYMcJiiOCkx2QZgIBMASXWzCRFMSxfqDBuZ8FuNMhcYTIEz4xBLO7seAl9+FvQTzpSXXyEwoKeZjLx2J2+9J1onx9ccnb5ioPeICRuiIKlSvu7VfFkDgc8k8luoktKSG+ZRpwcdae8VoQCzyt7OPzI1kSoZZw20gp2oYQcRkwpLBM007JkW2+KQraF5tZ9Ok8C1vG97lsByhd23r022joyTGpD+TZqWfXUX7K461GJJpohWoFlHshOaAwNj37XWKD8REpb0Qj7vABIfH+gXQhlJHBRCfKMRf12ILzU2yUbbQftwcPkcivNHGknEAkHIjWKk5lDH9uC2is5nWJHDCt/h/xa/AfvNbt28Kol+8yexRypnmorTzG9CBHq+pKrm48cBEGUxREiUjN7v5RGgJH+DB5nKkV4nH3P7mvWV+mkDcAXZPhDprplFl1Q7YV56OyjAY+dlpY6xyGopDz9DmmZifqLxR6mP9eSCIeIM9VsDJUwhfnnwyxRuuzZWFa+Adu8kuaBR8RqjcdE= 37 | -------------------------------------------------------------------------------- /examples/edgegrid/edgegrid.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "net/http" 7 | 8 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 9 | ) 10 | 11 | func main() { 12 | client := http.Client{} 13 | 14 | /* 15 | Init will try to use the environment and fallback to .edgerc. 16 | 17 | This function will check in order: 18 | 19 | AKAMAI_{SECTION}_* environment variables 20 | if using the default section, AKAMAI_* environment variables 21 | the specified (or default if none) section in .edgerc 22 | if not using the default section, AKAMAI_* environment variables 23 | This new function is the recommended way for instantiating an instance. 24 | 25 | The environment variables are: 26 | 27 | AKAMAI_HOST or AKAMAI_{SECTION}_HOST 28 | AKAMAI_CLIENT_TOKEN or AKAMAI_{SECTION}_CLIENT_TOKEN 29 | AKAMAI_CLIENT_SECRET or AKAMAI_{SECTION}_CLIENT_SECRET 30 | AKAMAI_ACCESS_TOKEN or AKAMAI_{SECTION}_ACCESS_TOKEN 31 | */ 32 | config, err := edgegrid.InitEdgeRc("~/.edgerc", "default") 33 | 34 | if err == nil { 35 | req, _ := http.NewRequest("GET", fmt.Sprintf("https://%s/diagnostic-tools/v2/ghost-locations/available", config.Host), nil) 36 | req = edgegrid.AddRequestHeader(config, req) 37 | resp, _ := client.Do(req) 38 | byt, _ := ioutil.ReadAll(resp.Body) 39 | fmt.Println(string(byt)) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /api-endpoints-v2/jwt_settings.go: -------------------------------------------------------------------------------- 1 | package apiendpoints 2 | 3 | type JWTSettings struct { 4 | Enabled bool `json:"enabled"` 5 | Settings struct { 6 | Location JWTSettingsLocationValue `json:"location"` 7 | ParamName string `json:"paramName"` 8 | ClockSkew int `json:"clockSkew"` 9 | Validation *struct { 10 | Claims []JWTClaim `json:"claims"` 11 | RsaPublicKeyA RsaPublicKey `json:"rsaPublicKeyA"` 12 | RsaPublicKeyB *RsaPublicKey `json:"rsaPublicKeyB,omitempty"` 13 | } `json:"validation"` 14 | } `json:"settings"` 15 | Resources map[int]JWTSettingsResource `json:"resources"` 16 | } 17 | 18 | type JWTSettingsResource struct { 19 | ResourceSettings 20 | Enabled bool `json:"enabled"` 21 | Notes *string `json:"notes,omitempty"` 22 | } 23 | 24 | type RsaPublicKey struct { 25 | Name string `json:"name"` 26 | Content string `json:"content"` 27 | } 28 | 29 | type JWTClaim struct { 30 | Name string `json:"name"` 31 | Validate bool `json:"validate"` 32 | Required bool `json:"required"` 33 | Value []string `json:"value"` 34 | Type string `json:"type"` 35 | } 36 | 37 | type JWTSettingsLocationValue string 38 | 39 | const ( 40 | JWTSettingsLocationHeader JWTSettingsLocationValue = "HEADER" 41 | JWTSettingsLocationCookie JWTSettingsLocationValue = "COOKIE" 42 | JWTSettingsLocationQuery JWTSettingsLocationValue = "QUERY" 43 | ) 44 | -------------------------------------------------------------------------------- /api-endpoints-v2/parameters.go: -------------------------------------------------------------------------------- 1 | package apiendpoints 2 | 3 | type Parameters struct { 4 | APIChildParameters []*Parameters `json:"apiChildParameters"` 5 | APIParameterID int `json:"apiParameterId"` 6 | APIParameterRequired bool `json:"apiParameterRequired"` 7 | APIParameterName string `json:"apiParameterName"` 8 | APIParameterLocation APIParameterLocationValue `json:"apiParameterLocation"` 9 | APIParameterType APIParameterTypeValue `json:"apiParameterType"` 10 | APIParameterNotes *string `json:"apiParameterNotes"` 11 | APIParamLogicID int `json:"apiParamLogicId"` 12 | Array bool `json:"array"` 13 | APIParameterRestriction struct { 14 | RangeRestriction struct { 15 | RangeMin int `json:"rangeMin"` 16 | RangeMax int `json:"rangeMax"` 17 | } `json:"rangeRestriction"` 18 | } `json:"apiParameterRestriction"` 19 | } 20 | 21 | type APIParameterLocationValue string 22 | type APIParameterTypeValue string 23 | 24 | const ( 25 | APIParameterLocationHeader APIParameterLocationValue = "header" 26 | APIParameterLocationCookie APIParameterLocationValue = "cookie" 27 | APIParameterLocationQuery APIParameterLocationValue = "query" 28 | APIParameterLocationBody APIParameterLocationValue = "body" 29 | 30 | APIParameterTypeString APIParameterTypeValue = "string" 31 | APIParameterTypeInteger APIParameterTypeValue = "integer" 32 | APIParameterTypeNumber APIParameterTypeValue = "number" 33 | APIParameterTypeBoolean APIParameterTypeValue = "boolean" 34 | APIParameterTypeJson APIParameterTypeValue = "json/xml" 35 | APIParameterTypeXml APIParameterTypeValue = "json/xml" 36 | ) 37 | -------------------------------------------------------------------------------- /configdns-v2/authorities.go: -------------------------------------------------------------------------------- 1 | package dnsv2 2 | 3 | import ( 4 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 5 | edge "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 6 | ) 7 | 8 | type AuthorityResponse struct { 9 | Contracts []struct { 10 | ContractID string `json:"contractId"` 11 | Authorities []string `json:"authorities"` 12 | } `json:"contracts"` 13 | } 14 | 15 | func NewAuthorityResponse(contract string) *AuthorityResponse { 16 | authorities := &AuthorityResponse{} 17 | return authorities 18 | } 19 | 20 | func GetAuthorities(contractId string) (*AuthorityResponse, error) { 21 | authorities := NewAuthorityResponse(contractId) 22 | 23 | req, err := client.NewRequest( 24 | Config, 25 | "GET", 26 | "/config-dns/v2/data/authorities?contractIds="+contractId, 27 | nil, 28 | ) 29 | if err != nil { 30 | return nil, err 31 | } 32 | 33 | edge.PrintHttpRequest(req, true) 34 | 35 | res, err := client.Do(Config, req) 36 | if err != nil { 37 | return nil, err 38 | } 39 | 40 | edge.PrintHttpResponse(res, true) 41 | 42 | if client.IsError(res) && res.StatusCode != 404 { 43 | return nil, client.NewAPIError(res) 44 | } else if res.StatusCode == 404 { 45 | return nil, &ZoneError{zoneName: contractId} 46 | } else { 47 | 48 | err = client.BodyJSON(res, authorities) 49 | if err != nil { 50 | return nil, err 51 | } 52 | return authorities, nil 53 | } 54 | } 55 | 56 | func GetNameServerRecordList(contractId string) ([]string, error) { 57 | 58 | NSrecords, err := GetAuthorities(contractId) 59 | 60 | if err != nil { 61 | return nil, err 62 | } 63 | 64 | var arrLength int 65 | for _, c := range NSrecords.Contracts { 66 | arrLength = len(c.Authorities) 67 | } 68 | 69 | ns := make([]string, 0, arrLength) 70 | 71 | for _, r := range NSrecords.Contracts { 72 | for _, n := range r.Authorities { 73 | ns = append(ns, n) 74 | } 75 | } 76 | return ns, nil 77 | } 78 | -------------------------------------------------------------------------------- /jsonhooks-v1/jsonhooks.go: -------------------------------------------------------------------------------- 1 | // Package jsonhooks adds hooks that are automatically called before JSON marshaling (PreMarshalJSON) and 2 | // after JSON unmarshaling (PostUnmarshalJSON). It does not do so recursively. 3 | package jsonhooks 4 | 5 | import ( 6 | "encoding/json" 7 | "reflect" 8 | ) 9 | 10 | // Marshal wraps encoding/json.Marshal, calls v.PreMarshalJSON() if it exists 11 | func Marshal(v interface{}) ([]byte, error) { 12 | if ImplementsPreJSONMarshaler(v) { 13 | err := v.(PreJSONMarshaler).PreMarshalJSON() 14 | if err != nil { 15 | return nil, err 16 | } 17 | } 18 | 19 | return json.Marshal(v) 20 | } 21 | 22 | // Unmarshal wraps encoding/json.Unmarshal, calls v.PostUnmarshalJSON() if it exists 23 | func Unmarshal(data []byte, v interface{}) error { 24 | err := json.Unmarshal(data, v) 25 | if err != nil { 26 | return err 27 | } 28 | 29 | if ImplementsPostJSONUnmarshaler(v) { 30 | err := v.(PostJSONUnmarshaler).PostUnmarshalJSON() 31 | if err != nil { 32 | return err 33 | } 34 | } 35 | 36 | return nil 37 | } 38 | 39 | // PreJSONMarshaler infers support for the PreMarshalJSON pre-hook 40 | type PreJSONMarshaler interface { 41 | PreMarshalJSON() error 42 | } 43 | 44 | // ImplementsPreJSONMarshaler checks for support for the PreMarshalJSON pre-hook 45 | func ImplementsPreJSONMarshaler(v interface{}) bool { 46 | value := reflect.ValueOf(v) 47 | if !value.IsValid() { 48 | return false 49 | } 50 | 51 | _, ok := value.Interface().(PreJSONMarshaler) 52 | return ok 53 | } 54 | 55 | // PostJSONUnmarshaler infers support for the PostUnmarshalJSON post-hook 56 | type PostJSONUnmarshaler interface { 57 | PostUnmarshalJSON() error 58 | } 59 | 60 | // ImplementsPostJSONUnmarshaler checks for support for the PostUnmarshalJSON post-hook 61 | func ImplementsPostJSONUnmarshaler(v interface{}) bool { 62 | value := reflect.ValueOf(v) 63 | if value.Kind() == reflect.Ptr && value.IsNil() { 64 | return false 65 | } 66 | 67 | _, ok := value.Interface().(PostJSONUnmarshaler) 68 | return ok 69 | } 70 | -------------------------------------------------------------------------------- /api-endpoints-v2/activations.go: -------------------------------------------------------------------------------- 1 | package apiendpoints 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 7 | ) 8 | 9 | type Activation struct { 10 | Networks []string `json:"networks"` 11 | NotificationRecipients []string `json:"notificationRecipients"` 12 | Notes string `json:"notes"` 13 | } 14 | 15 | type ActivateEndpointOptions struct { 16 | APIEndPointId int 17 | VersionNumber int 18 | } 19 | 20 | func ActivateEndpoint(options *ActivateEndpointOptions, activation *Activation) (*Activation, error) { 21 | req, err := client.NewJSONRequest( 22 | Config, 23 | "POST", 24 | fmt.Sprintf( 25 | "/api-definitions/v2/endpoints/%d/versions/%d/activate", 26 | options.APIEndPointId, 27 | options.VersionNumber, 28 | ), 29 | activation, 30 | ) 31 | 32 | if err != nil { 33 | return nil, err 34 | } 35 | 36 | res, err := client.Do(Config, req) 37 | 38 | if client.IsError(res) { 39 | return nil, client.NewAPIError(res) 40 | } 41 | 42 | return activation, nil 43 | } 44 | 45 | func DeactivateEndpoint(options *ActivateEndpointOptions, activation *Activation) (*Activation, error) { 46 | req, err := client.NewJSONRequest( 47 | Config, 48 | "DELETE", 49 | fmt.Sprintf( 50 | "/api-definitions/v2/endpoints/%d/versions/%d/deactivate", 51 | options.APIEndPointId, 52 | options.VersionNumber, 53 | ), 54 | activation, 55 | ) 56 | 57 | if err != nil { 58 | return nil, err 59 | } 60 | 61 | res, err := client.Do(Config, req) 62 | 63 | if client.IsError(res) { 64 | return nil, client.NewAPIError(res) 65 | } 66 | 67 | return activation, nil 68 | } 69 | 70 | func IsActive(endpoint *Endpoint, network string) bool { 71 | if network == "production" { 72 | if endpoint.ProductionStatus == StatusPending || endpoint.ProductionStatus == StatusActive { 73 | return true 74 | } 75 | } 76 | 77 | if network == "staging" { 78 | if endpoint.StagingStatus == StatusPending || endpoint.StagingStatus == StatusActive { 79 | return true 80 | } 81 | } 82 | 83 | return false 84 | } 85 | -------------------------------------------------------------------------------- /ccu-v3/purge.go: -------------------------------------------------------------------------------- 1 | package ccu 2 | 3 | import ( 4 | "errors" 5 | fmt "fmt" 6 | 7 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 8 | ) 9 | 10 | type PurgeTypeValue string 11 | type NetworkValue string 12 | 13 | var ( 14 | PurgeByUrl PurgeTypeValue = "url" 15 | PurgeByCpCode PurgeTypeValue = "cpcode" 16 | PurgeByCacheTag PurgeTypeValue = "tag" 17 | 18 | NetworkStaging NetworkValue = "staging" 19 | NetworkProduction NetworkValue = "production" 20 | ) 21 | 22 | type Purge struct { 23 | Objects []string `json:"objects""` 24 | } 25 | 26 | func NewPurge(objects []string) *Purge { 27 | return &Purge{ 28 | Objects: objects, 29 | } 30 | } 31 | 32 | func (p *Purge) Invalidate(purgeByType PurgeTypeValue, network NetworkValue) (*PurgeResponse, error) { 33 | return p.purge("invalidate", purgeByType, network) 34 | } 35 | 36 | func (p *Purge) Delete(purgeByType PurgeTypeValue, network NetworkValue) (*PurgeResponse, error) { 37 | return p.purge("delete", purgeByType, network) 38 | } 39 | 40 | func (p *Purge) purge(purgeMethod string, purgeByType PurgeTypeValue, network NetworkValue) (*PurgeResponse, error) { 41 | if len(p.Objects) == 0 { 42 | return nil, errors.New("one of more purge objects must be defined") 43 | } 44 | 45 | url := fmt.Sprintf( 46 | "/ccu/v3/%s/%s/%s", 47 | purgeMethod, 48 | purgeByType, 49 | network, 50 | ) 51 | 52 | req, err := client.NewJSONRequest(Config, "POST", url, p) 53 | if err != nil { 54 | return nil, err 55 | } 56 | 57 | res, err := client.Do(Config, req) 58 | if err != nil { 59 | return nil, err 60 | } 61 | 62 | if client.IsError(res) { 63 | return nil, client.NewAPIError(res) 64 | } 65 | 66 | purge := &PurgeResponse{} 67 | if err = client.BodyJSON(res, purge); err != nil { 68 | return nil, err 69 | } 70 | 71 | return purge, nil 72 | } 73 | 74 | type PurgeResponse struct { 75 | PurgeID string `json:"purgeId"` 76 | EstimatedSeconds int `json:"estimatedSeconds"` 77 | HTTPStatus int `json:"httpStatus"` 78 | Detail string `json:"detail"` 79 | SupportID string `json:"supportId"` 80 | } 81 | -------------------------------------------------------------------------------- /papi-v1/search.go: -------------------------------------------------------------------------------- 1 | package papi 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 7 | edge "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 8 | ) 9 | 10 | type SearchKey string 11 | 12 | const ( 13 | SearchByPropertyName SearchKey = "propertyName" 14 | SearchByHostname SearchKey = "hostname" 15 | SearchByEdgeHostname SearchKey = "edgeHostname" 16 | ) 17 | 18 | type SearchResult struct { 19 | Versions struct { 20 | Items []struct { 21 | UpdatedByUser string `json:"updatedByUser"` 22 | StagingStatus string `json:"stagingStatus"` 23 | AssetID string `json:"assetId"` 24 | PropertyName string `json:"propertyName"` 25 | PropertyVersion int `json:"propertyVersion"` 26 | UpdatedDate time.Time `json:"updatedDate"` 27 | ContractID string `json:"contractId"` 28 | AccountID string `json:"accountId"` 29 | GroupID string `json:"groupId"` 30 | PropertyID string `json:"propertyId"` 31 | ProductionStatus string `json:"productionStatus"` 32 | } `json:"items"` 33 | } `json:"versions"` 34 | } 35 | 36 | // Search searches for properties 37 | // 38 | // API Docs: https://developer.akamai.com/api/luna/papi/resources.html#postfindbyvalue 39 | // Endpoint: POST /papi/v1/search/find-by-value 40 | func Search(searchBy SearchKey, propertyName string, correlationid string) (*SearchResult, error) { 41 | req, err := client.NewJSONRequest( 42 | Config, 43 | "POST", 44 | "/papi/v1/search/find-by-value", 45 | map[string]string{(string)(searchBy): propertyName}, 46 | ) 47 | 48 | if err != nil { 49 | return nil, err 50 | } 51 | 52 | edge.PrintHttpRequestCorrelation(req, true, correlationid) 53 | 54 | res, err := client.Do(Config, req) 55 | if err != nil { 56 | return nil, err 57 | } 58 | 59 | edge.PrintHttpResponseCorrelation(res, true, correlationid) 60 | 61 | if client.IsError(res) { 62 | return nil, client.NewAPIError(res) 63 | } 64 | 65 | results := &SearchResult{} 66 | if err = client.BodyJSON(res, results); err != nil { 67 | return nil, err 68 | } 69 | 70 | if len(results.Versions.Items) == 0 { 71 | return nil, nil 72 | } 73 | 74 | return results, nil 75 | } 76 | -------------------------------------------------------------------------------- /api-endpoints-v2/cache_settings.go: -------------------------------------------------------------------------------- 1 | package apiendpoints 2 | 3 | type CacheSettings struct { 4 | Enabled bool `json:"enabled"` 5 | Option string `json:"option"` 6 | MaxAge *MaxAge `json:"maxAge"` 7 | ServeStale bool `json:"serveStale"` 8 | DownstreamCaching DownstreamCaching `json:"downstreamCaching"` 9 | ErrorCaching ErrorCaching `json:"errorCaching"` 10 | Resources map[int]CacheResource `json:"resources"` 11 | } 12 | 13 | type DownstreamCaching struct { 14 | Option string `json:"option"` 15 | Lifetime string `json:"lifetime"` 16 | MaxAge *MaxAge `json:"maxAge"` 17 | Headers string `json:"headers"` 18 | MarkAsPrivate bool `json:"markAsPrivate"` 19 | } 20 | 21 | type ErrorCaching struct { 22 | Enabled bool `json:"enabled"` 23 | MaxAge *MaxAge `json:"maxAge"` 24 | PreserveStale bool `json:"preserveStale"` 25 | } 26 | 27 | type MaxAge struct { 28 | Duration int `json:"duration"` 29 | Unit string `json:"unit"` 30 | } 31 | 32 | type CacheResource struct { 33 | ResourceSettings 34 | Option CacheResourceOptionValue `json:"option"` 35 | MaxAge *MaxAge `json:"maxAge"` 36 | ServeStale bool `json:"serveStale"` 37 | } 38 | 39 | type MaxAgeUnitValue string 40 | type CacheResourceOptionValue string 41 | 42 | const ( 43 | MaxAgeUnitSeconds MaxAgeUnitValue = "SECONDS" 44 | MaxAgeUnitMinutes MaxAgeUnitValue = "MINUTES" 45 | MaxAgeUnitHours MaxAgeUnitValue = "HOURS" 46 | MaxAgeUnitDays MaxAgeUnitValue = "DAYS" 47 | 48 | CacheResourceOptionCache CacheResourceOptionValue = "CACHE" 49 | CacheResourceOptionBypassCache CacheResourceOptionValue = "BYPASS_CACHE" 50 | CacheResourceOptionNoStore CacheResourceOptionValue = "NO_STORE" 51 | CacheResourceOptionHonorOriginCacheControl CacheResourceOptionValue = "HONOR_ORIGIN_CACHE_CONTROL" 52 | CacheResourceOptionHonorOriginExpires CacheResourceOptionValue = "HONOR_ORIGIN_EXPIRES" 53 | CacheResourceOptionHonorOriginCacheControlAndExpires CacheResourceOptionValue = "HONOR_ORIGIN_CACHE_CONTROL_AND_EXPIRES" 54 | ) 55 | -------------------------------------------------------------------------------- /papi-v1/client_settings.go: -------------------------------------------------------------------------------- 1 | package papi 2 | 3 | import ( 4 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 5 | edge "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 6 | ) 7 | 8 | // ClientSettings represents the PAPI client settings resource 9 | type ClientSettings struct { 10 | client.Resource 11 | RuleFormat string `json:"ruleFormat"` 12 | } 13 | 14 | // NewClientSettings creates a new ClientSettings 15 | func NewClientSettings() *ClientSettings { 16 | clientSettings := &ClientSettings{} 17 | clientSettings.Init() 18 | 19 | return clientSettings 20 | } 21 | 22 | // GetClientSettings populates ClientSettings 23 | // 24 | // API Docs: https://developer.akamai.com/api/luna/papi/resources.html#getclientsettings 25 | // Endpoint: GET /papi/v1/client-settings 26 | func (clientSettings *ClientSettings) GetClientSettings() error { 27 | req, err := client.NewRequest(Config, "GET", "/papi/v1/client-settings", nil) 28 | if err != nil { 29 | return err 30 | } 31 | 32 | edge.PrintHttpRequest(req, true) 33 | 34 | res, err := client.Do(Config, req) 35 | if err != nil { 36 | return err 37 | } 38 | 39 | edge.PrintHttpResponse(res, true) 40 | 41 | if client.IsError(res) { 42 | return client.NewAPIError(res) 43 | } 44 | 45 | if err := client.BodyJSON(res, clientSettings); err != nil { 46 | return err 47 | } 48 | 49 | return nil 50 | } 51 | 52 | // Save updates client settings 53 | // 54 | // API Docs: https://developer.akamai.com/api/luna/papi/resources.html#updateclientsettings 55 | // Endpoint: PUT /papi/v1/client-settings 56 | func (clientSettings *ClientSettings) Save() error { 57 | req, err := client.NewJSONRequest( 58 | Config, 59 | "PUT", 60 | "/papi/v1/client-settings", 61 | clientSettings, 62 | ) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | edge.PrintHttpRequest(req, true) 68 | 69 | res, err := client.Do(Config, req) 70 | if err != nil { 71 | return err 72 | } 73 | 74 | edge.PrintHttpResponse(res, true) 75 | 76 | if client.IsError(res) { 77 | return client.NewAPIError(res) 78 | } 79 | 80 | newClientSettings := NewClientSettings() 81 | if err := client.BodyJSON(res, newClientSettings); err != nil { 82 | return err 83 | } 84 | 85 | clientSettings.RuleFormat = newClientSettings.RuleFormat 86 | 87 | return nil 88 | } 89 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # EDGEGRID GOLANG RELEASE NOTES 2 | 3 | ## 2.0.0 (Oct 15, 2020) 4 | * [IMPORTANT] Breaking changes from earlier clients. Project updated to use v2 directory structure. 5 | * [ENHANCEMENT] PAPI - Api error return to the user when an activation or validation error occurs. 6 | * [NOTE] Project re-organized to prepare for additional APIs to be included in future versions of this library. 7 | 8 | ## 1.0.0 (Oct 15, 2020) 9 | * Official release for the EdgeGrid Golang library 10 | * DNSv2 - Zone create signature to pass blank instead of nil 11 | * PAPI - Return nil instead of error if no cp code was found 12 | * GTM - Datacenter API requires blank instead of nil 13 | 14 | ## 0.9.18 (Jul 13, 2020) 15 | * [AT-40][Add] Preliminary Logging CorrelationID 16 | 17 | ## 0.9.17 (Jun 9, 2020) 18 | * Corrected AKAMAICDN target parsing 19 | * Added endpoints for list zones, creating and updating multiple recordsets 20 | * Refactored recordsets into separate source file 21 | 22 | ## 0.9.16 (May 29, 2020) 23 | * Client-v1, Papi-v1 Updates 24 | * Add lock around http request creation. 25 | * papi - add logging to papi endpoints. 26 | 27 | ## 0.9.15 (May 15, 2020) 28 | * DNSv2 - Added CERT, TSLA Record parsing. Removed MX Record parsing 29 | 30 | ## 0.9.14 (May 12, 2020) 31 | * DNSv2 - Enhance RecordError functions 32 | 33 | ## 0.9.13 (Apr 26, 2020) 34 | * DNSv2 - filterZoneCreate check upper case Type 35 | 36 | ## 0.9.12 (Apr 21, 2020) 37 | * DNSv2 - Added optional arg to bypass dns record lock for create, update and delete functions. default preserves prior behavior 38 | 39 | ## 0.9.11 (Apr 13 , 2020) 40 | * DNSv2 Updates 41 | * Add additional fields, including TSIG, to zone 42 | * Support alias zone types 43 | * Add utility functions for Rdata parsing and process. 44 | * Add GetRecord, GetRecordSet functions 45 | * Add additional Recordset metadata 46 | * Add http request/response logging 47 | 48 | ## 0.9.10 (Mar 5, 2020) 49 | * Add support for caching Edgehostnames and Products 50 | * Support for cache in papi library for edgehostnames and products to minimize round trips to fetch repeated common data to avoid 51 | WAF deny rule IPBLOCK-BURST4-54013 issue 52 | 53 | ## 0.9.9 (Feb 29, 2020) 54 | * Add support for caching Contract, Groups, and Cp Codes 55 | * cache to minimize round trips on repeated common data fetches to avoid 56 | WAF deny rule IPBLOCK-BURST4-54013 issue 57 | 58 | ## 0.9.0 (Aug 6, 2019) 59 | * Added support for GTM 60 | -------------------------------------------------------------------------------- /api-endpoints-v2/resources.go: -------------------------------------------------------------------------------- 1 | package apiendpoints 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 7 | ) 8 | 9 | type Resources []Resource 10 | 11 | type Resource struct { 12 | APIResourceID int `json:"apiResourceId"` 13 | APIResourceName string `json:"apiResourceName"` 14 | ResourcePath string `json:"resourcePath"` 15 | Description string `json:"description"` 16 | LockVersion int `json:"lockVersion"` 17 | APIResourceClonedFromID *int `json:"apiResourceClonedFromId"` 18 | APIResourceLogicID int `json:"apiResourceLogicId"` 19 | CreatedBy string `json:"createdBy"` 20 | CreateDate string `json:"createDate"` 21 | UpdatedBy string `json:"updatedBy"` 22 | UpdateDate string `json:"updateDate"` 23 | APIResourceMethods Methods `json:"apiResourceMethods"` 24 | } 25 | 26 | type ResourceBaseInfo struct { 27 | APIResourceClonedFromID *int `json:"apiResourceClonedFromId"` 28 | APIResourceID int `json:"apiResourceId"` 29 | APIResourceLogicID int `json:"apiResourceLogicId"` 30 | APIResourceName string `json:"apiResourceName"` 31 | CreateDate string `json:"createDate"` 32 | CreatedBy string `json:"createdBy"` 33 | Description *string `json:"description"` 34 | Link *string `json:"link"` 35 | LockVersion int `json:"lockVersion"` 36 | Private bool `json:"private"` 37 | ResourcePath string `json:"resourcePath"` 38 | UpdateDate string `json:"updateDate"` 39 | UpdatedBy string `json:"updatedBy"` 40 | } 41 | 42 | type ResourceSettings struct { 43 | Path string `json:"path"` 44 | Methods []MethodValue `json:"methods"` 45 | InheritsFromEndpoint bool `json:"inheritsFromEndpoint"` 46 | } 47 | 48 | func GetResources(endpointId int, version int) (*Resources, error) { 49 | req, err := client.NewJSONRequest( 50 | Config, 51 | "GET", 52 | fmt.Sprintf( 53 | "/api-definitions/v2/endpoints/%d/versions/%d/resources", 54 | endpointId, 55 | version, 56 | ), 57 | nil, 58 | ) 59 | 60 | if err != nil { 61 | return nil, err 62 | } 63 | 64 | res, err := client.Do(Config, req) 65 | 66 | if client.IsError(res) { 67 | return nil, client.NewAPIError(res) 68 | } 69 | 70 | rep := &Resources{} 71 | if err = client.BodyJSON(res, rep); err != nil { 72 | return nil, err 73 | } 74 | 75 | return rep, nil 76 | } 77 | -------------------------------------------------------------------------------- /configgtm-v1_3/errors.go: -------------------------------------------------------------------------------- 1 | package configgtm 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type ConfigGTMError interface { 8 | error 9 | Network() bool 10 | NotFound() bool 11 | FailedToSave() bool 12 | ValidationFailed() bool 13 | } 14 | 15 | func IsConfigGTMError(e error) bool { 16 | _, ok := e.(ConfigGTMError) 17 | return ok 18 | } 19 | 20 | type CommonError struct { 21 | entityName string 22 | name string 23 | httpErrorMessage string 24 | apiErrorMessage string 25 | err error 26 | } 27 | 28 | func (e CommonError) SetItem(itemName string, itemVal interface{}) { 29 | switch itemName { 30 | case "entityName": 31 | e.entityName = itemVal.(string) 32 | case "name": 33 | e.name = itemVal.(string) 34 | case "httpErrorMessage": 35 | e.httpErrorMessage = itemVal.(string) 36 | case "apiErrorMessage": 37 | e.apiErrorMessage = itemVal.(string) 38 | case "err": 39 | e.err = itemVal.(error) 40 | } 41 | } 42 | 43 | func (e CommonError) GetItem(itemName string) interface{} { 44 | switch itemName { 45 | case "entityName": 46 | return e.entityName 47 | case "name": 48 | return e.name 49 | case "httpErrorMessage": 50 | return e.httpErrorMessage 51 | case "apiErrorMessage": 52 | return e.apiErrorMessage 53 | case "err": 54 | return e.err 55 | } 56 | 57 | return nil 58 | } 59 | 60 | func (e CommonError) Network() bool { 61 | if e.httpErrorMessage != "" { 62 | return true 63 | } 64 | return false 65 | } 66 | 67 | func (e CommonError) NotFound() bool { 68 | if e.err == nil && e.httpErrorMessage == "" && e.apiErrorMessage == "" { 69 | return true 70 | } 71 | return false 72 | } 73 | 74 | func (CommonError) FailedToSave() bool { 75 | return false 76 | } 77 | 78 | func (e CommonError) ValidationFailed() bool { 79 | if e.apiErrorMessage != "" { 80 | return true 81 | } 82 | return false 83 | } 84 | 85 | func (e CommonError) Error() string { 86 | 87 | if e.Network() { 88 | return fmt.Sprintf("%s \"%s\" network error: [%s]", e.entityName, e.name, e.httpErrorMessage) 89 | } 90 | 91 | if e.NotFound() { 92 | return fmt.Sprintf("%s \"%s\" not found.", e.entityName, e.name) 93 | } 94 | 95 | if e.FailedToSave() { 96 | return fmt.Sprintf("%s \"%s\" failed to save: [%s]", e.entityName, e.name, e.err.Error()) 97 | } 98 | 99 | if e.ValidationFailed() { 100 | return fmt.Sprintf("%s \"%s\" validation failed: [%s]", e.entityName, e.name, e.apiErrorMessage) 101 | } 102 | 103 | if e.err != nil { 104 | return e.err.Error() 105 | } 106 | 107 | return "" 108 | } 109 | -------------------------------------------------------------------------------- /configgtm-v1_4/errors.go: -------------------------------------------------------------------------------- 1 | package configgtm 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type ConfigGTMError interface { 8 | error 9 | Network() bool 10 | NotFound() bool 11 | FailedToSave() bool 12 | ValidationFailed() bool 13 | } 14 | 15 | func IsConfigGTMError(e error) bool { 16 | _, ok := e.(ConfigGTMError) 17 | return ok 18 | } 19 | 20 | type CommonError struct { 21 | entityName string 22 | name string 23 | httpErrorMessage string 24 | apiErrorMessage string 25 | err error 26 | } 27 | 28 | func (e CommonError) SetItem(itemName string, itemVal interface{}) { 29 | switch itemName { 30 | case "entityName": 31 | e.entityName = itemVal.(string) 32 | case "name": 33 | e.name = itemVal.(string) 34 | case "httpErrorMessage": 35 | e.httpErrorMessage = itemVal.(string) 36 | case "apiErrorMessage": 37 | e.apiErrorMessage = itemVal.(string) 38 | case "err": 39 | e.err = itemVal.(error) 40 | } 41 | } 42 | 43 | func (e CommonError) GetItem(itemName string) interface{} { 44 | switch itemName { 45 | case "entityName": 46 | return e.entityName 47 | case "name": 48 | return e.name 49 | case "httpErrorMessage": 50 | return e.httpErrorMessage 51 | case "apiErrorMessage": 52 | return e.apiErrorMessage 53 | case "err": 54 | return e.err 55 | } 56 | 57 | return nil 58 | } 59 | 60 | func (e CommonError) Network() bool { 61 | if e.httpErrorMessage != "" { 62 | return true 63 | } 64 | return false 65 | } 66 | 67 | func (e CommonError) NotFound() bool { 68 | if e.err == nil && e.httpErrorMessage == "" && e.apiErrorMessage == "" { 69 | return true 70 | } 71 | return false 72 | } 73 | 74 | func (CommonError) FailedToSave() bool { 75 | return false 76 | } 77 | 78 | func (e CommonError) ValidationFailed() bool { 79 | if e.apiErrorMessage != "" { 80 | return true 81 | } 82 | return false 83 | } 84 | 85 | func (e CommonError) Error() string { 86 | 87 | if e.Network() { 88 | return fmt.Sprintf("%s \"%s\" network error: [%s]", e.entityName, e.name, e.httpErrorMessage) 89 | } 90 | 91 | if e.NotFound() { 92 | return fmt.Sprintf("%s \"%s\" not found.", e.entityName, e.name) 93 | } 94 | 95 | if e.FailedToSave() { 96 | return fmt.Sprintf("%s \"%s\" failed to save: [%s]", e.entityName, e.name, e.err.Error()) 97 | } 98 | 99 | if e.ValidationFailed() { 100 | return fmt.Sprintf("%s \"%s\" validation failed: [%s]", e.entityName, e.name, e.apiErrorMessage) 101 | } 102 | 103 | if e.err != nil { 104 | return e.err.Error() 105 | } 106 | 107 | return "" 108 | } 109 | -------------------------------------------------------------------------------- /client-v1/client_test.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "net/http" 5 | "strings" 6 | "testing" 7 | 8 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func TestNewRequest(t *testing.T) { 13 | config := edgegrid.Config{ 14 | Host: "https://httpbin.org", 15 | AccessToken: "local-config", 16 | ClientSecret: "local-config", 17 | ClientToken: "local-config", 18 | } 19 | 20 | req, err := NewRequest(config, "GET", "/headers", nil) 21 | assert.NotNil(t, req) 22 | assert.NoError(t, err) 23 | assert.Equal(t, "https://httpbin.org/headers", req.URL.String()) 24 | verifyResponseConfig(t, config, req) 25 | } 26 | 27 | func TestNewRequestWithSwitchedAccount(t *testing.T) { 28 | config := edgegrid.Config{ 29 | Host: "https://httpbin.org", 30 | AccessToken: "local-config", 31 | ClientSecret: "local-config", 32 | ClientToken: "local-config", 33 | AccountKey: "ABC-DEF", 34 | } 35 | 36 | req, err := NewRequest(config, "GET", "/headers", nil) 37 | assert.NotNil(t, req) 38 | assert.NoError(t, err) 39 | assert.Equal(t, "https://httpbin.org/headers?accountSwitchKey=ABC-DEF", req.URL.String()) 40 | verifyResponseConfig(t, config, req) 41 | } 42 | 43 | func TestNewJSONRequest(t *testing.T) { 44 | config := edgegrid.Config{ 45 | Host: "https://httpbin.org", 46 | AccessToken: "local-config", 47 | ClientSecret: "local-config", 48 | ClientToken: "local-config", 49 | } 50 | 51 | req, err := NewJSONRequest(config, "GET", "/headers", config) 52 | assert.NotNil(t, req) 53 | assert.NoError(t, err) 54 | assert.Equal(t, "https://httpbin.org/headers", req.URL.String()) 55 | verifyResponseConfig(t, config, req) 56 | } 57 | 58 | func TestNewJSONRequestWithSwitchedAccount(t *testing.T) { 59 | config := edgegrid.Config{ 60 | Host: "https://httpbin.org", 61 | AccessToken: "local-config", 62 | ClientSecret: "local-config", 63 | ClientToken: "local-config", 64 | AccountKey: "ABC-DEF", 65 | } 66 | 67 | req, err := NewJSONRequest(config, "GET", "/headers", config) 68 | assert.NotNil(t, req) 69 | assert.NoError(t, err) 70 | assert.Equal(t, "https://httpbin.org/headers?accountSwitchKey=ABC-DEF", req.URL.String()) 71 | verifyResponseConfig(t, config, req) 72 | } 73 | 74 | func verifyResponseConfig(t *testing.T, config edgegrid.Config, req *http.Request) { 75 | resp, err := Do(config, req) 76 | assert.NotNil(t, resp) 77 | assert.NoError(t, err) 78 | 79 | json := make(map[string]interface{}) 80 | BodyJSON(resp, &json) 81 | 82 | assert.True(t, strings.Contains(json["headers"].(map[string]interface{})["Authorization"].(string), "local-config")) 83 | } 84 | -------------------------------------------------------------------------------- /configdns-v2/zone_test.go: -------------------------------------------------------------------------------- 1 | package dnsv2 2 | 3 | import ( 4 | "fmt" 5 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/jsonhooks-v1" 6 | "github.com/stretchr/testify/assert" 7 | "gopkg.in/h2non/gock.v1" 8 | "testing" 9 | ) 10 | 11 | func TestZone_JSON(t *testing.T) { 12 | responseBody := []byte(`{ 13 | "zone": "example.com", 14 | "type": "PRIMARY", 15 | "comment": "This is a test zone", 16 | "signAndServe": false 17 | }`) 18 | 19 | zonecreate := ZoneCreate{Zone: "example.com", Type: "PRIMARY", Masters: []string{""}, Comment: "This is a test zone", SignAndServe: false} 20 | zone := NewZone(zonecreate) 21 | err := jsonhooks.Unmarshal(responseBody, zone) 22 | assert.NoError(t, err) 23 | assert.Equal(t, zone.Zone, "example.com") 24 | assert.Equal(t, zone.Type, "PRIMARY") 25 | assert.Equal(t, zone.Comment, "This is a test zone") 26 | assert.Equal(t, zone.SignAndServe, false) 27 | } 28 | 29 | func TestGetZoneNames(t *testing.T) { 30 | 31 | dnsTestZone := "testzone.com" 32 | 33 | defer gock.Off() 34 | 35 | mock := gock.New(fmt.Sprintf("https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/config-dns/v2/zones/%s/names", dnsTestZone)) 36 | mock. 37 | Get(fmt.Sprintf("/config-dns/v2/zones/%s/names", dnsTestZone)). 38 | HeaderPresent("Authorization"). 39 | Reply(200). 40 | SetHeader("Content-Type", "application/json;charset=UTF-8"). 41 | BodyString(fmt.Sprintf(`{ 42 | "names":["test1.testzone.com","test2.testzone.com"] 43 | }`)) 44 | 45 | Init(config) 46 | nameList, err := GetZoneNames(dnsTestZone) 47 | assert.NoError(t, err) 48 | assert.Equal(t, assert.IsType(t, &ZoneNamesResponse{}, nameList), true) 49 | assert.Equal(t, len(nameList.Names), 2) 50 | 51 | } 52 | 53 | func TestGetZoneNameTypes(t *testing.T) { 54 | 55 | dnsTestZone := "testzone.com" 56 | dnsTestRecordName := "test.testzone.com" 57 | 58 | defer gock.Off() 59 | 60 | mock := gock.New(fmt.Sprintf("https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/config-dns/v2/zones/%s/names/%s/types", dnsTestZone, dnsTestRecordName)) 61 | mock. 62 | Get(fmt.Sprintf("/config-dns/v2/zones/%s/names/%s/types", dnsTestZone, dnsTestRecordName)). 63 | HeaderPresent("Authorization"). 64 | Reply(200). 65 | SetHeader("Content-Type", "application/json;charset=UTF-8"). 66 | BodyString(fmt.Sprintf(`{ 67 | "types":["CNAME", "AKAMAICDN"] 68 | }`)) 69 | 70 | Init(config) 71 | typeList, err := GetZoneNameTypes(dnsTestRecordName, dnsTestZone) 72 | assert.NoError(t, err) 73 | assert.Equal(t, assert.IsType(t, &ZoneNameTypesResponse{}, typeList), true) 74 | assert.Equal(t, len(typeList.Types), 2) 75 | 76 | } 77 | -------------------------------------------------------------------------------- /configdns-v1/errors.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type ConfigDNSError interface { 8 | error 9 | Network() bool 10 | NotFound() bool 11 | FailedToSave() bool 12 | ValidationFailed() bool 13 | } 14 | 15 | func IsConfigDNSError(e error) bool { 16 | _, ok := e.(ConfigDNSError) 17 | return ok 18 | } 19 | 20 | type ZoneError struct { 21 | zoneName string 22 | httpErrorMessage string 23 | apiErrorMessage string 24 | err error 25 | } 26 | 27 | func (e *ZoneError) Network() bool { 28 | if e.httpErrorMessage != "" { 29 | return true 30 | } 31 | return false 32 | } 33 | 34 | func (e *ZoneError) NotFound() bool { 35 | if e.err == nil && e.httpErrorMessage == "" && e.apiErrorMessage == "" { 36 | return true 37 | } 38 | return false 39 | } 40 | 41 | func (e *ZoneError) FailedToSave() bool { 42 | return false 43 | } 44 | 45 | func (e *ZoneError) ValidationFailed() bool { 46 | if e.apiErrorMessage != "" { 47 | return true 48 | } 49 | return false 50 | } 51 | 52 | func (e *ZoneError) Error() string { 53 | if e.Network() { 54 | return fmt.Sprintf("Zone \"%s\" network error: [%s]", e.zoneName, e.httpErrorMessage) 55 | } 56 | 57 | if e.NotFound() { 58 | return fmt.Sprintf("Zone \"%s\" not found.", e.zoneName) 59 | } 60 | 61 | if e.FailedToSave() { 62 | return fmt.Sprintf("Zone \"%s\" failed to save: [%s]", e.zoneName, e.err.Error()) 63 | } 64 | 65 | if e.ValidationFailed() { 66 | return fmt.Sprintf("Zone \"%s\" validation failed: [%s]", e.zoneName, e.apiErrorMessage) 67 | } 68 | 69 | if e.err != nil { 70 | return e.err.Error() 71 | } 72 | 73 | return "" 74 | } 75 | 76 | type RecordError struct { 77 | fieldName string 78 | httpErrorMessage string 79 | err error 80 | } 81 | 82 | func (e *RecordError) Network() bool { 83 | if e.httpErrorMessage != "" { 84 | return true 85 | } 86 | return false 87 | } 88 | 89 | func (e *RecordError) NotFound() bool { 90 | return false 91 | } 92 | 93 | func (e *RecordError) FailedToSave() bool { 94 | if e.fieldName == "" { 95 | return true 96 | } 97 | return false 98 | } 99 | 100 | func (e *RecordError) ValidationFailed() bool { 101 | if e.fieldName != "" { 102 | return true 103 | } 104 | return false 105 | } 106 | 107 | func (e *RecordError) Error() string { 108 | if e.Network() { 109 | return fmt.Sprintf("Record network error: [%s]", e.httpErrorMessage) 110 | } 111 | 112 | if e.NotFound() { 113 | return fmt.Sprintf("Record not found.") 114 | } 115 | 116 | if e.FailedToSave() { 117 | return fmt.Sprintf("Record failed to save: [%s]", e.err.Error()) 118 | } 119 | 120 | if e.ValidationFailed() { 121 | return fmt.Sprintf("Record validation failed for field [%s]", e.fieldName) 122 | } 123 | 124 | return "" 125 | } 126 | -------------------------------------------------------------------------------- /examples/client/client.go: -------------------------------------------------------------------------------- 1 | //An example Diagnostic Tools v1 API Client 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "log" 7 | "math/rand" 8 | "time" 9 | 10 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 11 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 12 | ) 13 | 14 | func random(min int, max int) int { 15 | rand.Seed(time.Now().UTC().UnixNano()) 16 | random := rand.Intn(max-min) + min 17 | 18 | return random 19 | } 20 | 21 | //Location ghost location type 22 | type Location struct { 23 | ID string `json:"id"` 24 | Value string `json:"value"` 25 | } 26 | 27 | //LocationsResponse response type for ghost locations 28 | type LocationsResponse struct { 29 | Locations []Location `json:"locations"` 30 | } 31 | 32 | //DigResponse response type for dig API 33 | type DigResponse struct { 34 | Dig struct { 35 | Hostname string `json:"hostname"` 36 | QueryType string `json:"queryType"` 37 | Result string `json:"result"` 38 | ErrorString string `json:"errorString"` 39 | } `json:"digInfo"` 40 | } 41 | 42 | func main() { 43 | Example() 44 | } 45 | 46 | func Example() { 47 | config, err := edgegrid.InitEdgeRc("~/.edgerc", "default") 48 | config.Debug = false 49 | if err == nil { 50 | if err == nil { 51 | fmt.Println("Requesting locations that support the diagnostic-tools API.") 52 | 53 | req, err := client.NewRequest( 54 | config, 55 | "GET", 56 | "/diagnostic-tools/v2/ghost-locations/available", 57 | nil, 58 | ) 59 | if err != nil { 60 | log.Fatal(err.Error()) 61 | } 62 | 63 | res, err := client.Do(config, req) 64 | if err != nil { 65 | log.Fatal(err.Error()) 66 | return 67 | } 68 | 69 | locationsResponse := LocationsResponse{} 70 | client.BodyJSON(res, &locationsResponse) 71 | 72 | if err != nil { 73 | log.Fatal(err.Error()) 74 | } 75 | 76 | fmt.Printf("There are %d locations that can run dig in the Akamai Network\n", len(locationsResponse.Locations)) 77 | 78 | if len(locationsResponse.Locations) == 0 { 79 | log.Fatal("No locations found") 80 | } 81 | 82 | location := locationsResponse.Locations[random(0, len(locationsResponse.Locations))-1] 83 | 84 | fmt.Println("We will make our call from " + location.Value) 85 | 86 | fmt.Println("Running dig from " + location.Value) 87 | 88 | client.Client.Timeout = 5 * time.Minute 89 | req, err = client.NewRequest( 90 | config, 91 | "GET", 92 | "/diagnostic-tools/v2/ghost-locations/"+location.ID+"/dig-info?hostName=developer.akamai.com&queryType=A", 93 | nil, 94 | ) 95 | if err != nil { 96 | log.Fatal(err.Error()) 97 | return 98 | } 99 | 100 | res, err = client.Do(config, req) 101 | if err != nil { 102 | log.Fatal(err.Error()) 103 | return 104 | } 105 | 106 | digResponse := DigResponse{} 107 | client.BodyJSON(res, &digResponse) 108 | fmt.Println(digResponse.Dig.Result) 109 | } else { 110 | log.Fatal(err.Error()) 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /reportsgtm-v1/datacenter.go: -------------------------------------------------------------------------------- 1 | package reportsgtm 2 | 3 | import ( 4 | "strconv" 5 | 6 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 7 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/configgtm-v1_3" 8 | 9 | "fmt" 10 | ) 11 | 12 | // 13 | // Support gtm reports thru Edgegrid 14 | // Based on 1.0 Schema 15 | // 16 | 17 | // Datacenter Traffic Report Structs 18 | type DCTMeta struct { 19 | Uri string `json:uri"` 20 | Domain string `json:"domain"` 21 | Interval string `json:"interval,omitempty"` 22 | DatacenterId int `json:"datacenterId"` 23 | DatacenterNickname string `json:"datacenterNickname"` 24 | Start string `json:"start"` 25 | End string `json:"end"` 26 | } 27 | 28 | type DCTDRow struct { 29 | Name string `json:"name"` 30 | Requests int64 `json:"requests"` 31 | Status string `json:"status"` 32 | } 33 | 34 | type DCTData struct { 35 | Timestamp string `json:"timestamp"` 36 | Properties []*DCTDRow `json:"properties"` 37 | } 38 | 39 | // Response structure returned by the Datacenter Traffic API 40 | type DcTrafficResponse struct { 41 | Metadata *DCTMeta `json:"metadata"` 42 | DataRows []*DCTData `json:"dataRows"` 43 | DataSummary interface{} `json:"dataSummary"` 44 | Links []*configgtm.Link `json:"links"` 45 | } 46 | 47 | // GetTrafficPerDatacenter retrieves Report Traffic per datacenter. Opt args - start, end. 48 | func GetTrafficPerDatacenter(domainName string, datacenterID int, optArgs map[string]string) (*DcTrafficResponse, error) { 49 | stat := &DcTrafficResponse{} 50 | hostURL := fmt.Sprintf("/gtm-api/v1/reports/traffic/domains/%s/datacenters/%s", domainName, strconv.Itoa(datacenterID)) 51 | 52 | req, err := client.NewRequest( 53 | Config, 54 | "GET", 55 | hostURL, 56 | nil, 57 | ) 58 | if err != nil { 59 | return nil, err 60 | } 61 | 62 | // Look for and process optional query params 63 | q := req.URL.Query() 64 | for k, v := range optArgs { 65 | switch k { 66 | case "start": 67 | fallthrough 68 | case "end": 69 | q.Add(k, v) 70 | } 71 | } 72 | if optArgs != nil { 73 | // time stamps require urlencoded content header 74 | setEncodedHeader(req) 75 | req.URL.RawQuery = q.Encode() 76 | } 77 | 78 | // print/log the request if warranted 79 | printHttpRequest(req, true) 80 | 81 | res, err := client.Do(Config, req) 82 | if err != nil { 83 | return nil, err 84 | } 85 | 86 | // print/log the response if warranted 87 | printHttpResponse(res, true) 88 | 89 | if client.IsError(res) && res.StatusCode != 404 { 90 | return nil, client.NewAPIError(res) 91 | } else if res.StatusCode == 404 { 92 | cErr := configgtm.CommonError{} 93 | cErr.SetItem("entityName", "Datacenter") 94 | cErr.SetItem("name", strconv.Itoa(datacenterID)) 95 | return nil, cErr 96 | } else { 97 | err = client.BodyJSON(res, stat) 98 | if err != nil { 99 | return nil, err 100 | } 101 | 102 | return stat, nil 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /edgegrid/signer_test.go: -------------------------------------------------------------------------------- 1 | package edgegrid 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | "net/url" 9 | "regexp" 10 | "testing" 11 | 12 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/jsonhooks-v1" 13 | "github.com/stretchr/testify/assert" 14 | ) 15 | 16 | var ( 17 | testFile = "../testdata/testdata.json" 18 | timestamp = "20140321T19:34:21+0000" 19 | nonce = "nonce-xx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 20 | config = Config{ 21 | Host: "https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/", 22 | AccessToken: "akab-access-token-xxx-xxxxxxxxxxxxxxxx", 23 | ClientToken: "akab-client-token-xxx-xxxxxxxxxxxxxxxx", 24 | ClientSecret: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=", 25 | MaxBody: 2048, 26 | Debug: true, 27 | HeaderToSign: []string{ 28 | "X-Test1", 29 | "X-Test2", 30 | "X-Test3", 31 | }, 32 | } 33 | ) 34 | 35 | type JSONTests struct { 36 | Tests []Test `json:"tests"` 37 | } 38 | type Test struct { 39 | Name string `json:"testName"` 40 | Request struct { 41 | Method string `json:"method"` 42 | Path string `json:"path"` 43 | Headers []map[string]string `json:"headers"` 44 | Data string `json:"data"` 45 | } `json:"request"` 46 | ExpectedAuthorization string `json:"expectedAuthorization"` 47 | } 48 | 49 | func TestMakeEdgeTimeStamp(t *testing.T) { 50 | actual := makeEdgeTimeStamp() 51 | expected := regexp.MustCompile(`^\d{4}[0-1][0-9][0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-5][0-9]\+0000$`) 52 | if assert.Regexp(t, expected, actual, "Fail: Regex do not match") { 53 | t.Log("Pass: Regex matches") 54 | } 55 | } 56 | 57 | func TestCreateNonce(t *testing.T) { 58 | actual := createNonce() 59 | for i := 0; i < 100; i++ { 60 | expected := createNonce() 61 | assert.NotEqual(t, actual, expected, "Fail: Nonce matches") 62 | } 63 | } 64 | 65 | func TestCreateAuthHeader(t *testing.T) { 66 | var edgegrid JSONTests 67 | byt, err := ioutil.ReadFile(testFile) 68 | if err != nil { 69 | t.Fatalf("Test file not found, err %s", err) 70 | } 71 | url, err := url.Parse(config.Host) 72 | if err != nil { 73 | t.Fatalf("URL is not parsable, err %s", err) 74 | } 75 | err = jsonhooks.Unmarshal(byt, &edgegrid) 76 | if err != nil { 77 | t.Fatalf("JSON is not parsable, err %s", err) 78 | } 79 | for _, edge := range edgegrid.Tests { 80 | url.Path = edge.Request.Path 81 | req, _ := http.NewRequest( 82 | edge.Request.Method, 83 | url.String(), 84 | bytes.NewBuffer([]byte(edge.Request.Data)), 85 | ) 86 | for _, header := range edge.Request.Headers { 87 | for k, v := range header { 88 | req.Header.Set(k, v) 89 | } 90 | } 91 | SetupLogging() 92 | actual := createAuthHeader(config, req, timestamp, nonce) 93 | if assert.Equal(t, edge.ExpectedAuthorization, actual, fmt.Sprintf("Fail: %s", edge.Name)) { 94 | t.Logf("Pass: %s\n", edge.Name) 95 | t.Logf("Expected: %s - Actual %s", edge.ExpectedAuthorization, actual) 96 | } 97 | 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /papi-v1/ruleformats.go: -------------------------------------------------------------------------------- 1 | package papi 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "sort" 7 | 8 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 9 | edge "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 10 | "github.com/xeipuuv/gojsonschema" 11 | ) 12 | 13 | // RuleFormats is a collection of available rule formats 14 | type RuleFormats struct { 15 | client.Resource 16 | RuleFormats struct { 17 | Items []string `json:"items"` 18 | } `json:"ruleFormats"` 19 | } 20 | 21 | // NewRuleFormats creates a new RuleFormats 22 | func NewRuleFormats() *RuleFormats { 23 | ruleFormats := &RuleFormats{} 24 | ruleFormats.Init() 25 | 26 | return ruleFormats 27 | } 28 | 29 | // GetRuleFormats populates RuleFormats 30 | // 31 | // API Docs: https://developer.akamai.com/api/luna/papi/resources.html#listruleformats 32 | // Endpoint: GET /papi/v1/rule-formats 33 | func (ruleFormats *RuleFormats) GetRuleFormats(correlationid string) error { 34 | req, err := client.NewRequest( 35 | Config, 36 | "GET", 37 | "/papi/v1/rule-formats", 38 | nil, 39 | ) 40 | if err != nil { 41 | return err 42 | } 43 | 44 | edge.PrintHttpRequestCorrelation(req, true, correlationid) 45 | 46 | res, err := client.Do(Config, req) 47 | if err != nil { 48 | return err 49 | } 50 | 51 | edge.PrintHttpResponseCorrelation(res, true, correlationid) 52 | 53 | if client.IsError(res) { 54 | return client.NewAPIError(res) 55 | } 56 | 57 | if err := client.BodyJSON(res, ruleFormats); err != nil { 58 | return err 59 | } 60 | 61 | sort.Strings(ruleFormats.RuleFormats.Items) 62 | 63 | return nil 64 | } 65 | 66 | func (ruleFormats *RuleFormats) GetLatest(correlationid string) (string, error) { 67 | if len(ruleFormats.RuleFormats.Items) == 0 { 68 | err := ruleFormats.GetRuleFormats(correlationid) 69 | if err != nil { 70 | return "", err 71 | } 72 | } 73 | 74 | return ruleFormats.RuleFormats.Items[len(ruleFormats.RuleFormats.Items)-1], nil 75 | } 76 | 77 | // GetSchema fetches the schema for a given product and rule format 78 | // 79 | // API Docs: https://developer.akamai.com/api/luna/papi/resources.html#getaruleformatsschema 80 | // Endpoint: /papi/v1/schemas/products/{productId}/{ruleFormat} 81 | func (ruleFormats *RuleFormats) GetSchema(product string, ruleFormat string, correlationid string) (*gojsonschema.Schema, error) { 82 | req, err := client.NewRequest( 83 | Config, 84 | "GET", 85 | fmt.Sprintf( 86 | "/papi/v1/schemas/products/%s/%s", 87 | product, 88 | ruleFormat, 89 | ), 90 | nil, 91 | ) 92 | if err != nil { 93 | return nil, err 94 | } 95 | 96 | edge.PrintHttpRequestCorrelation(req, true, correlationid) 97 | 98 | res, err := client.Do(Config, req) 99 | if err != nil { 100 | return nil, err 101 | } 102 | 103 | edge.PrintHttpResponseCorrelation(res, true, correlationid) 104 | 105 | if client.IsError(res) { 106 | return nil, client.NewAPIError(res) 107 | } 108 | 109 | schemaBytes, _ := ioutil.ReadAll(res.Body) 110 | schemaBody := string(schemaBytes) 111 | loader := gojsonschema.NewStringLoader(schemaBody) 112 | schema, err := gojsonschema.NewSchema(loader) 113 | 114 | return schema, err 115 | } 116 | -------------------------------------------------------------------------------- /papi-v1/service.go: -------------------------------------------------------------------------------- 1 | package papi 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 7 | "github.com/patrickmn/go-cache" 8 | ) 9 | 10 | var ( 11 | Config edgegrid.Config 12 | Profilecache = cache.New(5*time.Minute, 10*time.Minute) 13 | ) 14 | 15 | // GetGroups retrieves all groups 16 | func GetGroups() (*Groups, error) { 17 | groups := NewGroups() 18 | if err := groups.GetGroups(""); err != nil { 19 | return nil, err 20 | } 21 | 22 | return groups, nil 23 | } 24 | 25 | // GetContracts retrieves all contracts 26 | func GetContracts() (*Contracts, error) { 27 | contracts := NewContracts() 28 | if err := contracts.GetContracts(""); err != nil { 29 | return nil, err 30 | } 31 | 32 | return contracts, nil 33 | } 34 | 35 | // GetProducts retrieves all products 36 | func GetProducts(contract *Contract) (*Products, error) { 37 | products := NewProducts() 38 | if err := products.GetProducts(contract, ""); err != nil { 39 | return nil, err 40 | } 41 | 42 | return products, nil 43 | } 44 | 45 | // GetEdgeHostnames retrieves all edge hostnames 46 | func GetEdgeHostnames(contract *Contract, group *Group, options string) (*EdgeHostnames, error) { 47 | edgeHostnames := NewEdgeHostnames() 48 | if err := edgeHostnames.GetEdgeHostnames(contract, group, options, ""); err != nil { 49 | return nil, err 50 | } 51 | 52 | return edgeHostnames, nil 53 | } 54 | 55 | // GetCpCodes creates a new CpCodes struct and populates it with all CP Codes associated with a contract/group 56 | // 57 | // API Docs: https://developer.akamai.com/api/luna/papi/resources.html#listcpcodes 58 | func GetCpCodes(contract *Contract, group *Group) (*CpCodes, error) { 59 | cpcodes := NewCpCodes(contract, group) 60 | if err := cpcodes.GetCpCodes(""); err != nil { 61 | return nil, err 62 | } 63 | 64 | return cpcodes, nil 65 | } 66 | 67 | // GetProperties retrieves all properties for a given contract/group 68 | func GetProperties(contract *Contract, group *Group) (*Properties, error) { 69 | properties := NewProperties() 70 | if err := properties.GetProperties(contract, group, ""); err != nil { 71 | return nil, err 72 | } 73 | 74 | return properties, nil 75 | } 76 | 77 | // GetVersions retrieves all versions for a given property 78 | func GetVersions(property *Property) (*Versions, error) { 79 | versions := NewVersions() 80 | if err := versions.GetVersions(property, ""); err != nil { 81 | return nil, err 82 | } 83 | 84 | return versions, nil 85 | } 86 | 87 | // GetAvailableBehaviors retrieves all available behaviors for a property 88 | func GetAvailableBehaviors(property *Property) (*AvailableBehaviors, error) { 89 | availableBehaviors := NewAvailableBehaviors() 90 | if err := availableBehaviors.GetAvailableBehaviors(property); err != nil { 91 | return nil, err 92 | } 93 | 94 | return availableBehaviors, nil 95 | } 96 | 97 | // GetAvailableCriteria retrieves all available criteria for a property 98 | func GetAvailableCriteria(property *Property) (*AvailableCriteria, error) { 99 | availableCriteria := NewAvailableCriteria() 100 | if err := availableCriteria.GetAvailableCriteria(property); err != nil { 101 | return nil, err 102 | } 103 | 104 | return availableCriteria, nil 105 | } 106 | -------------------------------------------------------------------------------- /papi-v1/customoverrides_test.go: -------------------------------------------------------------------------------- 1 | package papi 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/stretchr/testify/assert" 8 | "gopkg.in/h2non/gock.v1" 9 | ) 10 | 11 | func TestCustomOverrides_GetCustomOverrides(t *testing.T) { 12 | defer gock.Off() 13 | 14 | mock := gock.New("https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/papi/v1/custom-overrides") 15 | mock. 16 | Get("/papi/v1/custom-overrides"). 17 | HeaderPresent("Authorization"). 18 | Reply(200). 19 | SetHeader("Content-Type", "application/json"). 20 | BodyString(`{ 21 | "accountId": "act_1-1TJZFB", 22 | "customOverrides": { 23 | "items": [ 24 | { 25 | "overrideId": "cbo_12345", 26 | "displayName": "MDC Behavior", 27 | "description": "Multiple Domain Configuration can be used to ...", 28 | "name": "mdc", 29 | "status": "ACTIVE", 30 | "updatedByUser": "jsikkela", 31 | "updatedDate": "2017-04-24T12:34:56Z" 32 | } 33 | ] 34 | } 35 | }`) 36 | 37 | Init(config) 38 | 39 | overrides := NewCustomOverrides() 40 | err := overrides.GetCustomOverrides() 41 | 42 | assert.NoError(t, err) 43 | assert.Len(t, overrides.CustomOverrides.Items, 1) 44 | assert.Equal(t, "cbo_12345", overrides.CustomOverrides.Items[0].OverrideID) 45 | assert.Equal(t, "mdc", overrides.CustomOverrides.Items[0].Name) 46 | assert.Equal(t, "ACTIVE", overrides.CustomOverrides.Items[0].Status) 47 | assert.Equal(t, "MDC Behavior", overrides.CustomOverrides.Items[0].DisplayName) 48 | assert.Equal(t, "Multiple Domain Configuration can be used to ...", overrides.CustomOverrides.Items[0].Description) 49 | time, _ := time.Parse("2006-01-02T15:04:05Z", "2017-04-24T12:34:56Z") 50 | assert.Equal(t, time, overrides.CustomOverrides.Items[0].UpdatedDate) 51 | assert.Equal(t, "jsikkela", overrides.CustomOverrides.Items[0].UpdatedByUser) 52 | } 53 | 54 | func TestCustomOverride_GetCustomOverride(t *testing.T) { 55 | defer gock.Off() 56 | 57 | mock := gock.New("https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/papi/v1/custom-overrides/cbo_12345") 58 | mock. 59 | Get("/papi/v1/custom-overrides/cbo_12345"). 60 | HeaderPresent("Authorization"). 61 | Reply(200). 62 | SetHeader("Content-Type", "application/json"). 63 | BodyString(`{ 64 | "accountId": "act_1-1TJZFB", 65 | "customOverrides": { 66 | "items": [ 67 | { 68 | "overrideId": "cbo_12345", 69 | "displayName": "MDC Behavior", 70 | "description": "Multiple Domain Configuration can be used to ...", 71 | "name": "mdc", 72 | "status": "ACTIVE", 73 | "updatedByUser": "jsikkela", 74 | "updatedDate": "2017-04-24T12:34:56Z" 75 | } 76 | ] 77 | } 78 | }`) 79 | 80 | Init(config) 81 | 82 | override := NewCustomOverride(NewCustomOverrides()) 83 | override.OverrideID = "cbo_12345" 84 | err := override.GetCustomOverride() 85 | 86 | assert.NoError(t, err) 87 | assert.Equal(t, "cbo_12345", override.OverrideID) 88 | assert.Equal(t, "mdc", override.Name) 89 | assert.Equal(t, "ACTIVE", override.Status) 90 | assert.Equal(t, "MDC Behavior", override.DisplayName) 91 | assert.Equal(t, "Multiple Domain Configuration can be used to ...", override.Description) 92 | time, _ := time.Parse("2006-01-02T15:04:05Z", "2017-04-24T12:34:56Z") 93 | assert.Equal(t, time, override.UpdatedDate) 94 | assert.Equal(t, "jsikkela", override.UpdatedByUser) 95 | } 96 | -------------------------------------------------------------------------------- /papi-v1/products.go: -------------------------------------------------------------------------------- 1 | package papi 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | 7 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 8 | edge "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 9 | "github.com/patrickmn/go-cache" 10 | ) 11 | 12 | // Products represents a collection of products 13 | type Products struct { 14 | client.Resource 15 | AccountID string `json:"accountId"` 16 | ContractID string `json:"contractId"` 17 | Products struct { 18 | Items []*Product `json:"items"` 19 | } `json:"products"` 20 | } 21 | 22 | // NewProducts creates a new Products 23 | func NewProducts() *Products { 24 | products := &Products{} 25 | products.Init() 26 | 27 | return products 28 | } 29 | 30 | // PostUnmarshalJSON is called after JSON unmarshaling into EdgeHostnames 31 | // 32 | // See: jsonhooks-v1/jsonhooks.Unmarshal() 33 | func (products *Products) PostUnmarshalJSON() error { 34 | products.Init() 35 | 36 | for key, product := range products.Products.Items { 37 | products.Products.Items[key].parent = products 38 | if err := product.PostUnmarshalJSON(); err != nil { 39 | return err 40 | } 41 | } 42 | 43 | return nil 44 | } 45 | 46 | // GetProducts populates Products with product data 47 | // 48 | // API Docs: https://developer.akamai.com/api/luna/papi/resources.html#listproducts 49 | // Endpoint: GET /papi/v1/products/{?contractId} 50 | func (products *Products) GetProducts(contract *Contract, correlationid string) error { 51 | cacheproducts, found := Profilecache.Get("products") 52 | if found { 53 | json.Unmarshal(cacheproducts.([]byte), products) 54 | return nil 55 | } else { 56 | req, err := client.NewRequest( 57 | Config, 58 | "GET", 59 | fmt.Sprintf( 60 | "/papi/v1/products?contractId=%s", 61 | contract.ContractID, 62 | ), 63 | nil, 64 | ) 65 | if err != nil { 66 | return err 67 | } 68 | 69 | edge.PrintHttpRequestCorrelation(req, true, correlationid) 70 | 71 | res, err := client.Do(Config, req) 72 | if err != nil { 73 | return err 74 | } 75 | 76 | edge.PrintHttpResponseCorrelation(res, true, correlationid) 77 | 78 | if client.IsError(res) { 79 | return client.NewAPIError(res) 80 | } 81 | 82 | if err = client.BodyJSON(res, products); err != nil { 83 | return err 84 | } 85 | 86 | byt, _ := json.Marshal(products) 87 | Profilecache.Set("products", byt, cache.DefaultExpiration) 88 | return nil 89 | } 90 | 91 | } 92 | 93 | // FindProduct finds a specific product by ID 94 | func (products *Products) FindProduct(id string) (*Product, error) { 95 | var product *Product 96 | var productFound bool 97 | for _, product = range products.Products.Items { 98 | if product.ProductID == id { 99 | productFound = true 100 | break 101 | } 102 | } 103 | 104 | if !productFound { 105 | return nil, fmt.Errorf("Unable to find product: \"%s\"", id) 106 | } 107 | 108 | return product, nil 109 | } 110 | 111 | // Product represents a product resource 112 | type Product struct { 113 | client.Resource 114 | parent *Products 115 | ProductName string `json:"productName"` 116 | ProductID string `json:"productId"` 117 | } 118 | 119 | // NewProduct creates a new Product 120 | func NewProduct(parent *Products) *Product { 121 | product := &Product{parent: parent} 122 | product.Init() 123 | 124 | return product 125 | } 126 | -------------------------------------------------------------------------------- /papi-v1/custombehaviors_test.go: -------------------------------------------------------------------------------- 1 | package papi 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/stretchr/testify/assert" 8 | "gopkg.in/h2non/gock.v1" 9 | ) 10 | 11 | func TestCustomBehaviors_GetCustomBehaviors(t *testing.T) { 12 | defer gock.Off() 13 | 14 | mock := gock.New("https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/papi/v1/custom-behaviors") 15 | mock. 16 | Get("/papi/v1/custom-behaviors"). 17 | HeaderPresent("Authorization"). 18 | Reply(200). 19 | SetHeader("Content-Type", "application/json"). 20 | BodyString(`{ 21 | "accountId": "act_1-1TJZFB", 22 | "customBehaviors": { 23 | "items": [ 24 | { 25 | "behaviorId": "cbe_12345", 26 | "name": "DLR", 27 | "status": "ACTIVE", 28 | "displayName": "Custom Download Receipt", 29 | "description": "Setting custom download receipt. Uses PMUSER_LOG variable.", 30 | "updatedDate": "2017-04-24T12:34:56Z", 31 | "updatedByUser": "jsikkela" 32 | } 33 | ] 34 | } 35 | }`) 36 | 37 | Init(config) 38 | 39 | behaviors := NewCustomBehaviors() 40 | err := behaviors.GetCustomBehaviors() 41 | 42 | assert.NoError(t, err) 43 | assert.Len(t, behaviors.CustomBehaviors.Items, 1) 44 | assert.Equal(t, "cbe_12345", behaviors.CustomBehaviors.Items[0].BehaviorID) 45 | assert.Equal(t, "DLR", behaviors.CustomBehaviors.Items[0].Name) 46 | assert.Equal(t, "ACTIVE", behaviors.CustomBehaviors.Items[0].Status) 47 | assert.Equal(t, "Custom Download Receipt", behaviors.CustomBehaviors.Items[0].DisplayName) 48 | assert.Equal(t, "Setting custom download receipt. Uses PMUSER_LOG variable.", behaviors.CustomBehaviors.Items[0].Description) 49 | time, _ := time.Parse("2006-01-02T15:04:05Z", "2017-04-24T12:34:56Z") 50 | assert.Equal(t, time, behaviors.CustomBehaviors.Items[0].UpdatedDate) 51 | assert.Equal(t, "jsikkela", behaviors.CustomBehaviors.Items[0].UpdatedByUser) 52 | } 53 | 54 | func TestCustomBehavior_GetCustomBehavior(t *testing.T) { 55 | defer gock.Off() 56 | 57 | mock := gock.New("https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/papi/v1/custom-behaviors/cbe_12345") 58 | mock. 59 | Get("/papi/v1/custom-behaviors/cbe_12345"). 60 | HeaderPresent("Authorization"). 61 | Reply(200). 62 | SetHeader("Content-Type", "application/json"). 63 | BodyString(`{ 64 | "accountId": "act_1-1TJZFB", 65 | "customBehaviors": { 66 | "items": [ 67 | { 68 | "behaviorId": "cbe_12345", 69 | "name": "DLR", 70 | "status": "ACTIVE", 71 | "displayName": "Custom Download Receipt", 72 | "description": "Setting custom download receipt. Uses PMUSER_LOG variable.", 73 | "updatedDate": "2017-04-24T12:34:56Z", 74 | "updatedByUser": "jsikkela" 75 | } 76 | ] 77 | } 78 | }`) 79 | 80 | Init(config) 81 | 82 | behavior := NewCustomBehavior(NewCustomBehaviors()) 83 | behavior.BehaviorID = "cbe_12345" 84 | err := behavior.GetCustomBehavior() 85 | 86 | assert.NoError(t, err) 87 | assert.Equal(t, "cbe_12345", behavior.BehaviorID) 88 | assert.Equal(t, "DLR", behavior.Name) 89 | assert.Equal(t, "ACTIVE", behavior.Status) 90 | assert.Equal(t, "Custom Download Receipt", behavior.DisplayName) 91 | assert.Equal(t, "Setting custom download receipt. Uses PMUSER_LOG variable.", behavior.Description) 92 | time, _ := time.Parse("2006-01-02T15:04:05Z", "2017-04-24T12:34:56Z") 93 | assert.Equal(t, time, behavior.UpdatedDate) 94 | assert.Equal(t, "jsikkela", behavior.UpdatedByUser) 95 | } 96 | -------------------------------------------------------------------------------- /configdns-v2/recordsets_test.go: -------------------------------------------------------------------------------- 1 | package dnsv2 2 | 3 | import ( 4 | "testing" 5 | //edge "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 6 | "fmt" 7 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/jsonhooks-v1" 8 | "github.com/stretchr/testify/assert" 9 | "gopkg.in/h2non/gock.v1" 10 | ) 11 | 12 | var recordsetBody = []byte(fmt.Sprintf(`{ 13 | "recordsets": [{ 14 | "name": "new.%s", 15 | "type": "CNAME", 16 | "ttl": 900, 17 | "rdata": ["www.example.com"] 18 | }, 19 | { 20 | "name": "a_rec_%s", 21 | "type": "A", 22 | "ttl": 900, 23 | "rdata": ["10.0.0.10"] 24 | }]}`, dnsTestZone, dnsTestZone)) 25 | 26 | func createTestRecordsets() *Recordsets { 27 | 28 | rs := &Recordsets{} 29 | jsonhooks.Unmarshal(recordsetBody, rs) 30 | 31 | return rs 32 | 33 | } 34 | 35 | func TestListRecordsets(t *testing.T) { 36 | 37 | /* 38 | // for live testing 39 | config, err := edge.Init("","") 40 | if err != nil { 41 | t.Fatalf("TestListRecordsets failed initializing: %s", err.Error()) 42 | } 43 | */ 44 | 45 | defer gock.Off() 46 | 47 | mock := gock.New(fmt.Sprintf("https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/config-dns/v2/zones/%s/recordsets", dnsTestZone)) 48 | mock. 49 | Get(fmt.Sprintf("/config-dns/v2/zones/%s/recordsets", dnsTestZone)). 50 | HeaderPresent("Authorization"). 51 | Reply(200). 52 | SetHeader("Content-Type", "application/json;charset=UTF-8"). 53 | BodyString(fmt.Sprintf(`{ 54 | "metadata": { 55 | "totalElements":2 56 | }, 57 | "recordsets": [ 58 | { 59 | "name": "new.%s", 60 | "type": "CNAME", 61 | "ttl": 900, 62 | "rdata": ["www.example.com"] 63 | }, 64 | { 65 | "name": "a_rec_%s", 66 | "type": "A", 67 | "ttl": 900, 68 | "rdata": ["10.0.0.10"] 69 | }]}`, dnsTestZone, dnsTestZone)) 70 | 71 | Init(config) 72 | listResp, err := GetRecordsets(dnsTestZone) 73 | assert.NoError(t, err) 74 | assert.Equal(t, int(len(listResp.Recordsets)), listResp.Metadata.TotalElements) 75 | 76 | } 77 | 78 | func TestCreateRecordsets(t *testing.T) { 79 | 80 | defer gock.Off() 81 | 82 | mock := gock.New(fmt.Sprintf("https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/config-dns/v2/zones/%s/recordsets", dnsTestZone)) 83 | mock. 84 | Post(fmt.Sprintf("/config-dns/v2/zones/%s/recordsets", dnsTestZone)). 85 | HeaderPresent("Authorization"). 86 | Reply(204). 87 | SetHeader("Content-Type", "application/json;charset=UTF-8") 88 | 89 | Init(config) 90 | sets := createTestRecordsets() 91 | err := sets.Save(dnsTestZone) 92 | assert.NoError(t, err) 93 | 94 | } 95 | 96 | func TestUpdateRecordsets(t *testing.T) { 97 | 98 | defer gock.Off() 99 | 100 | mock := gock.New(fmt.Sprintf("https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/config-dns/v2/zones/%s/recordsets", dnsTestZone)) 101 | mock. 102 | Put(fmt.Sprintf("/config-dns/v2/zones/%s/recordsets", dnsTestZone)). 103 | HeaderPresent("Authorization"). 104 | Reply(204). 105 | SetHeader("Content-Type", "application/json;charset=UTF-8") 106 | 107 | Init(config) 108 | sets := createTestRecordsets() 109 | err := sets.Update(dnsTestZone) 110 | assert.NoError(t, err) 111 | 112 | } 113 | -------------------------------------------------------------------------------- /client-v1/errors.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "net/http" 7 | "strings" 8 | 9 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/jsonhooks-v1" 10 | ) 11 | 12 | // APIError exposes an Akamai OPEN Edgegrid Error 13 | type APIError struct { 14 | error 15 | Type string `json:"type"` 16 | Title string `json:"title"` 17 | Status int `json:"status"` 18 | Detail string `json:"detail"` 19 | Errors []APIErrorDetail `json:"errors"` 20 | Problems []APIErrorDetail `json:"problems"` 21 | Instance string `json:"instance"` 22 | Method string `json:"method"` 23 | ServerIP string `json:"serverIp"` 24 | ClientIP string `json:"clientIp"` 25 | RequestID string `json:"requestId"` 26 | RequestTime string `json:"requestTime"` 27 | Response *http.Response `json:"-"` 28 | RawBody string `json:"-"` 29 | } 30 | 31 | type APIErrorDetail struct { 32 | Type string `json:"type"` 33 | Title string `json:"title"` 34 | Detail string `json:"detail"` 35 | RejectedValue string `json:"rejectedValue"` 36 | } 37 | 38 | func (error APIError) Error() string { 39 | var errorDetails string 40 | if len(error.Errors) > 0 { 41 | for _, e := range error.Errors { 42 | errorDetails = fmt.Sprintf("%s \n %s", errorDetails, e) 43 | } 44 | } 45 | if len(error.Problems) > 0 { 46 | for _, e := range error.Problems { 47 | errorDetails = fmt.Sprintf("%s \n %s", errorDetails, e) 48 | } 49 | } 50 | return strings.TrimSpace(fmt.Sprintf("API Error: %d %s %s More Info %s\n %s", error.Status, error.Title, error.Detail, error.Type, errorDetails)) 51 | } 52 | 53 | // NewAPIError creates a new API error based on a Response, 54 | // or http.Response-like. 55 | func NewAPIError(response *http.Response) APIError { 56 | // TODO: handle this error 57 | body, _ := ioutil.ReadAll(response.Body) 58 | 59 | return NewAPIErrorFromBody(response, body) 60 | } 61 | 62 | // NewAPIErrorFromBody creates a new API error, allowing you to pass in a body 63 | // 64 | // This function is intended to be used after the body has already been read for 65 | // other purposes. 66 | func NewAPIErrorFromBody(response *http.Response, body []byte) APIError { 67 | error := APIError{} 68 | if err := jsonhooks.Unmarshal(body, &error); err != nil { 69 | error.Status = response.StatusCode 70 | error.Title = response.Status 71 | } 72 | 73 | error.Response = response 74 | error.RawBody = string(body) 75 | 76 | return error 77 | } 78 | 79 | // IsInformational determines if a response was informational (1XX status) 80 | func IsInformational(r *http.Response) bool { 81 | return r.StatusCode > 99 && r.StatusCode < 200 82 | } 83 | 84 | // IsSuccess determines if a response was successful (2XX status) 85 | func IsSuccess(r *http.Response) bool { 86 | return r.StatusCode > 199 && r.StatusCode < 300 87 | } 88 | 89 | // IsRedirection determines if a response was a redirect (3XX status) 90 | func IsRedirection(r *http.Response) bool { 91 | return r.StatusCode > 299 && r.StatusCode < 400 92 | } 93 | 94 | // IsClientError determines if a response was a client error (4XX status) 95 | func IsClientError(r *http.Response) bool { 96 | return r.StatusCode > 399 && r.StatusCode < 500 97 | } 98 | 99 | // IsServerError determines if a response was a server error (5XX status) 100 | func IsServerError(r *http.Response) bool { 101 | return r.StatusCode > 499 && r.StatusCode < 600 102 | } 103 | 104 | // IsError determines if the response was a client or server error (4XX or 5XX status) 105 | func IsError(r *http.Response) bool { 106 | return r.StatusCode > 399 && r.StatusCode < 600 107 | } 108 | -------------------------------------------------------------------------------- /configgtm-v1_3/common.go: -------------------------------------------------------------------------------- 1 | package configgtm 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | ) 7 | 8 | // 9 | // Common data types and methods 10 | // Based on 1.3 schemas 11 | // 12 | 13 | // Append url args to req 14 | func appendReqArgs(req *http.Request, queryArgs map[string]string) { 15 | 16 | // Look for optional args 17 | if len(queryArgs) > 0 { 18 | q := req.URL.Query() 19 | for argName, argVal := range queryArgs { 20 | q.Add(argName, argVal) 21 | } 22 | req.URL.RawQuery = q.Encode() 23 | } 24 | 25 | } 26 | 27 | // default schema version 28 | // TODO: retrieve from environment or elsewhere in Service Init 29 | var schemaVersion string = "1.3" 30 | 31 | // internal method to set version. passed in as string 32 | func setVersionHeader(req *http.Request, version string) { 33 | 34 | req.Header.Set("Accept", fmt.Sprintf("application/vnd.config-gtm.v%s+json", version)) 35 | 36 | if req.Method != "GET" { 37 | req.Header.Set("Content-Type", fmt.Sprintf("application/vnd.config-gtm.v%s+json", version)) 38 | } 39 | 40 | return 41 | 42 | } 43 | 44 | // response Status is returned on Create, Update or Delete operations for all entity types 45 | type ResponseStatus struct { 46 | ChangeId string `json:"changeId,omitempty"` 47 | Links *[]Link `json:"links,omitempty"` 48 | Message string `json:"message,omitempty"` 49 | PassingValidation bool `json:"passingValidation,omitempty"` 50 | PropagationStatus string `json:"propagationStatus,omitempty"` 51 | PropagationStatusDate string `json:"propagationStatusDate,omitempty"` 52 | } 53 | 54 | // NewResponseStatus returns a new ResponseStatus struct 55 | func NewResponseStatus() *ResponseStatus { 56 | 57 | return &ResponseStatus{} 58 | 59 | } 60 | 61 | // Generic response structs 62 | type ResponseBody struct { 63 | Resource interface{} `json:"resource"` 64 | Status *ResponseStatus `json:"status"` 65 | } 66 | 67 | // Response structs by Entity Type 68 | type DomainResponse struct { 69 | Resource *Domain `json:"resource"` 70 | Status *ResponseStatus `json:"status"` 71 | } 72 | 73 | type DatacenterResponse struct { 74 | Status *ResponseStatus `json:"status"` 75 | Resource *Datacenter `json:"resource"` 76 | } 77 | 78 | type PropertyResponse struct { 79 | Resource *Property `json:"resource"` 80 | Status *ResponseStatus `json:"status"` 81 | } 82 | 83 | type ResourceResponse struct { 84 | Resource *Resource `json:"resource"` 85 | Status *ResponseStatus `json:"status"` 86 | } 87 | 88 | type CidrMapResponse struct { 89 | Resource *CidrMap `json:"resource"` 90 | Status *ResponseStatus `json:"status"` 91 | } 92 | 93 | type GeoMapResponse struct { 94 | Resource *GeoMap `json:"resource"` 95 | Status *ResponseStatus `json:"status"` 96 | } 97 | 98 | type AsMapResponse struct { 99 | Resource *AsMap `json:"resource"` 100 | Status *ResponseStatus `json:"status"` 101 | } 102 | 103 | // Probably THE most common type 104 | type Link struct { 105 | Rel string `json:"rel"` 106 | Href string `json:"href"` 107 | } 108 | 109 | // 110 | type LoadObject struct { 111 | LoadObject string `json:"loadObject,omitempty"` 112 | LoadObjectPort int `json:"loadObjectPort,omitempty"` 113 | LoadServers []string `json:"loadServers,omitempty"` 114 | } 115 | 116 | // NewLoadObject returns a new LoadObject structure 117 | func NewLoadObject() *LoadObject { 118 | return &LoadObject{} 119 | } 120 | 121 | type DatacenterBase struct { 122 | Nickname string `json:"nickname"` 123 | DatacenterId int `json:"datacenterId"` 124 | } 125 | 126 | // NewDatacenterBase returns a new DatacenterBase structure 127 | func NewDatacenterBase() *DatacenterBase { 128 | return &DatacenterBase{} 129 | } 130 | -------------------------------------------------------------------------------- /configgtm-v1_4/common.go: -------------------------------------------------------------------------------- 1 | package configgtm 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | ) 7 | 8 | // 9 | // Common data types and methods 10 | // Based on 1.3 schemas 11 | // 12 | 13 | // Append url args to req 14 | func appendReqArgs(req *http.Request, queryArgs map[string]string) { 15 | 16 | // Look for optional args 17 | if len(queryArgs) > 0 { 18 | q := req.URL.Query() 19 | for argName, argVal := range queryArgs { 20 | q.Add(argName, argVal) 21 | } 22 | req.URL.RawQuery = q.Encode() 23 | } 24 | 25 | } 26 | 27 | // default schema version 28 | // TODO: retrieve from environment or elsewhere in Service Init 29 | var schemaVersion string = "1.4" 30 | 31 | // internal method to set version. passed in as string 32 | func setVersionHeader(req *http.Request, version string) { 33 | 34 | req.Header.Set("Accept", fmt.Sprintf("application/vnd.config-gtm.v%s+json", version)) 35 | 36 | if req.Method != "GET" { 37 | req.Header.Set("Content-Type", fmt.Sprintf("application/vnd.config-gtm.v%s+json", version)) 38 | } 39 | 40 | return 41 | 42 | } 43 | 44 | // response Status is returned on Create, Update or Delete operations for all entity types 45 | type ResponseStatus struct { 46 | ChangeId string `json:"changeId,omitempty"` 47 | Links *[]Link `json:"links,omitempty"` 48 | Message string `json:"message,omitempty"` 49 | PassingValidation bool `json:"passingValidation,omitempty"` 50 | PropagationStatus string `json:"propagationStatus,omitempty"` 51 | PropagationStatusDate string `json:"propagationStatusDate,omitempty"` 52 | } 53 | 54 | // NewResponseStatus returns a new ResponseStatus struct 55 | func NewResponseStatus() *ResponseStatus { 56 | 57 | return &ResponseStatus{} 58 | 59 | } 60 | 61 | // Generic response structs 62 | type ResponseBody struct { 63 | Resource interface{} `json:"resource"` 64 | Status *ResponseStatus `json:"status"` 65 | } 66 | 67 | // Response structs by Entity Type 68 | type DomainResponse struct { 69 | Resource *Domain `json:"resource"` 70 | Status *ResponseStatus `json:"status"` 71 | } 72 | 73 | type DatacenterResponse struct { 74 | Status *ResponseStatus `json:"status"` 75 | Resource *Datacenter `json:"resource"` 76 | } 77 | 78 | type PropertyResponse struct { 79 | Resource *Property `json:"resource"` 80 | Status *ResponseStatus `json:"status"` 81 | } 82 | 83 | type ResourceResponse struct { 84 | Resource *Resource `json:"resource"` 85 | Status *ResponseStatus `json:"status"` 86 | } 87 | 88 | type CidrMapResponse struct { 89 | Resource *CidrMap `json:"resource"` 90 | Status *ResponseStatus `json:"status"` 91 | } 92 | 93 | type GeoMapResponse struct { 94 | Resource *GeoMap `json:"resource"` 95 | Status *ResponseStatus `json:"status"` 96 | } 97 | 98 | type AsMapResponse struct { 99 | Resource *AsMap `json:"resource"` 100 | Status *ResponseStatus `json:"status"` 101 | } 102 | 103 | // Probably THE most common type 104 | type Link struct { 105 | Rel string `json:"rel"` 106 | Href string `json:"href"` 107 | } 108 | 109 | // 110 | type LoadObject struct { 111 | LoadObject string `json:"loadObject,omitempty"` 112 | LoadObjectPort int `json:"loadObjectPort,omitempty"` 113 | LoadServers []string `json:"loadServers,omitempty"` 114 | } 115 | 116 | // NewLoadObject returns a new LoadObject structure 117 | func NewLoadObject() *LoadObject { 118 | return &LoadObject{} 119 | } 120 | 121 | type DatacenterBase struct { 122 | Nickname string `json:"nickname,omitempty"` 123 | DatacenterId int `json:"datacenterId"` 124 | } 125 | 126 | // NewDatacenterBase returns a new DatacenterBase structure 127 | func NewDatacenterBase() *DatacenterBase { 128 | return &DatacenterBase{} 129 | } 130 | -------------------------------------------------------------------------------- /reportsgtm-v1/datacenter_test.go: -------------------------------------------------------------------------------- 1 | package reportsgtm 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "gopkg.in/h2non/gock.v1" 8 | ) 9 | 10 | // Verify GetTrafficPerDatacenter. 11 | func TestGetTrafficPerDatacenter(t *testing.T) { 12 | 13 | defer gock.Off() 14 | 15 | mock := gock.New("https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/gtm-api/v1/reports/traffic/domains/gtmtest.akadns.net/datacenters/3200") 16 | mock. 17 | Get("/gtm-api/v1/reports/traffic/domains/gtmtest.akadns.net/datacenters/3200"). 18 | HeaderPresent("Authorization"). 19 | Reply(200). 20 | SetHeader("Content-Type", "application/json"). 21 | BodyString(`{ 22 | "metadata": { 23 | "domain": "gtmtest.akadns.net", 24 | "datacenterId": 3200, 25 | "datacenterNickname": "Winterfell", 26 | "start": "2016-11-23T00:00:00Z", 27 | "end": "2016-11-23T00:10:00Z", 28 | "interval": "FIVE_MINUTE", 29 | "uri": "https://akaa-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net/gtm-api/v1/reports/traffic/domains/gtmtest.akadns.net/datacenters?start=2016-11-23T00:00:00Z&end=2016-11-23T00:10:00Z" 30 | }, 31 | "dataRows": [ { 32 | "timestamp": "2016-11-23T00:00:00Z", 33 | "properties": [ { 34 | "name": "www", 35 | "requests": 45, 36 | "status": "1" 37 | } ] 38 | }, 39 | { 40 | "timestamp": "2016-11-23T00:05:00Z", 41 | "properties": [ { 42 | "name": "www", 43 | "requests": 45, 44 | "status": "1" 45 | } ] 46 | } ], 47 | "links": [ { 48 | "rel": "self", 49 | "href": "https://akaa-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net/gtm-api/v1/reports/traffic/domains/gtmtest.akadns.net/datacenters?start=2016-11-23T00:00:00Z&2016-11-23T00:10:00Z" 50 | } ] 51 | }`) 52 | 53 | Init(config) 54 | 55 | optArgs := make(map[string]string) 56 | optArgs["start"] = "2016-11-23T00:00:00Z" 57 | optArgs["end"] = "2016-11-23T00:10:00Z" 58 | 59 | testDCTraffic, err := GetTrafficPerDatacenter(gtmTestDomain, 3200, optArgs) 60 | assert.NoError(t, err) 61 | assert.Equal(t, "gtmtest.akadns.net", testDCTraffic.Metadata.Domain) 62 | assert.Equal(t, testDCTraffic.DataRows[0].Timestamp, "2016-11-23T00:00:00Z") 63 | 64 | } 65 | 66 | // Verify failed case for TrafficPerDatacenter. 67 | func TestGetBadTrafficPerDatacenter(t *testing.T) { 68 | 69 | defer gock.Off() 70 | 71 | mock := gock.New("https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/gtm-api/v1/reports/traffic/domains/gtmtest.akadns.net/datacenters/9999") 72 | mock. 73 | Get("/gtm-api/v1/reports/traffic/domains/gtmtest.akadns.net/datacenters/9999"). 74 | HeaderPresent("Authorization"). 75 | Reply(404). 76 | SetHeader("Content-Type", "application/json"). 77 | BodyString(`{ 78 | }`) 79 | 80 | Init(config) 81 | 82 | optArgs := make(map[string]string) 83 | _, err := GetTrafficPerDatacenter(gtmTestDomain, 9999, optArgs) 84 | 85 | assert.Error(t, err) 86 | } 87 | -------------------------------------------------------------------------------- /configdns-v1/record_test.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestRecord_ContainsHelper(t *testing.T) { 10 | tm1 := []string{ 11 | "test1", 12 | "test2", 13 | "test3", 14 | } 15 | 16 | assert.Equal(t, contains(tm1, "test1"), true) 17 | assert.Equal(t, contains(tm1, "test2"), true) 18 | assert.Equal(t, contains(tm1, "test3"), true) 19 | assert.Equal(t, contains(tm1, "test4"), false) 20 | } 21 | 22 | func TestRecord_ARecord(t *testing.T) { 23 | a := NewARecord() 24 | f := []string{ 25 | "name", 26 | "ttl", 27 | "active", 28 | "target", 29 | } 30 | assert.Equal(t, a.fieldMap, f) 31 | assert.Equal(t, a.fieldMap, a.GetAllowedFields()) 32 | assert.Equal(t, a.SetField("name", "test1"), nil) 33 | assert.Equal(t, a.SetField("doesntExist", "test1"), &RecordError{fieldName: "doesntExist"}) 34 | a.SetField("ttl", 900) 35 | a.SetField("active", true) 36 | a.SetField("target", "test2") 37 | assert.Equal(t, a.ToMap(), map[string]interface{}{ 38 | "name": "test1", 39 | "ttl": 900, 40 | "active": true, 41 | "target": "test2", 42 | }) 43 | } 44 | 45 | func TestRecord_AllRecords_WrongTypes(t *testing.T) { 46 | a := NewARecord() 47 | e := a.SetField("name", 1) 48 | assert.Equal(t, e, &RecordError{fieldName: "name"}) 49 | 50 | a1 := NewAaaaRecord() 51 | e1 := a1.SetField("name", 1) 52 | assert.Equal(t, e1, &RecordError{fieldName: "name"}) 53 | 54 | a2 := NewAfsdbRecord() 55 | e = a2.SetField("name", 1) 56 | assert.Equal(t, e, &RecordError{fieldName: "name"}) 57 | 58 | a3 := NewCnameRecord() 59 | e = a3.SetField("name", 1) 60 | assert.Equal(t, e, &RecordError{fieldName: "name"}) 61 | 62 | a4 := NewDnskeyRecord() 63 | e = a4.SetField("name", 1) 64 | assert.Equal(t, e, &RecordError{fieldName: "name"}) 65 | 66 | a5 := NewDsRecord() 67 | e = a5.SetField("name", 1) 68 | assert.Equal(t, e, &RecordError{fieldName: "name"}) 69 | 70 | a6 := NewHinfoRecord() 71 | e = a6.SetField("name", 1) 72 | assert.Equal(t, e, &RecordError{fieldName: "name"}) 73 | 74 | a7 := NewLocRecord() 75 | e = a7.SetField("name", 1) 76 | assert.Equal(t, e, &RecordError{fieldName: "name"}) 77 | 78 | a8 := NewMxRecord() 79 | e = a8.SetField("name", 1) 80 | assert.Equal(t, e, &RecordError{fieldName: "name"}) 81 | 82 | a9 := NewNaptrRecord() 83 | e = a9.SetField("name", 1) 84 | assert.Equal(t, e, &RecordError{fieldName: "name"}) 85 | 86 | a10 := NewNsRecord() 87 | e = a10.SetField("name", 1) 88 | assert.Equal(t, e, &RecordError{fieldName: "name"}) 89 | 90 | a11 := NewNsec3Record() 91 | e = a11.SetField("name", 1) 92 | assert.Equal(t, e, &RecordError{fieldName: "name"}) 93 | 94 | a12 := NewNsec3paramRecord() 95 | e = a12.SetField("name", 1) 96 | assert.Equal(t, e, &RecordError{fieldName: "name"}) 97 | 98 | a13 := NewPtrRecord() 99 | e = a13.SetField("name", 1) 100 | assert.Equal(t, e, &RecordError{fieldName: "name"}) 101 | 102 | a14 := NewRpRecord() 103 | e = a14.SetField("name", 1) 104 | assert.Equal(t, e, &RecordError{fieldName: "name"}) 105 | 106 | a15 := NewRrsigRecord() 107 | e = a15.SetField("name", 1) 108 | assert.Equal(t, e, &RecordError{fieldName: "name"}) 109 | 110 | a16 := NewSoaRecord() 111 | e = a16.SetField("ttl", "test") 112 | assert.Equal(t, e, &RecordError{fieldName: "ttl"}) 113 | 114 | a17 := NewSpfRecord() 115 | e = a17.SetField("name", 1) 116 | assert.Equal(t, e, &RecordError{fieldName: "name"}) 117 | 118 | a18 := NewSrvRecord() 119 | e = a18.SetField("name", 1) 120 | assert.Equal(t, e, &RecordError{fieldName: "name"}) 121 | 122 | a19 := NewSshfpRecord() 123 | e = a19.SetField("name", 1) 124 | assert.Equal(t, e, &RecordError{fieldName: "name"}) 125 | 126 | a20 := NewTxtRecord() 127 | e = a20.SetField("name", 1) 128 | assert.Equal(t, e, &RecordError{fieldName: "name"}) 129 | } 130 | -------------------------------------------------------------------------------- /apikey-manager-v1/keys.go: -------------------------------------------------------------------------------- 1 | package apikeymanager 2 | 3 | import ( 4 | "encoding/json" 5 | "io/ioutil" 6 | 7 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 8 | ) 9 | 10 | type Keys []int 11 | 12 | type Key struct { 13 | Id int `json:"id,omitempty"` 14 | Value string `json:"value,omitempty"` 15 | Label string `json:"label,omitempty"` 16 | Tags []string `json:"tags,omitempty"` 17 | CollectionName string `json:"collectionName,omitempty"` 18 | CollectionId int `json:"collectionId,omitempty"` 19 | Description string `json:"description,omitempty"` 20 | Revoked bool `json:"revoked,omitempty"` 21 | Dirty bool `json:"dirty,omitempty"` 22 | CreatedAt string `json:"createdAt,omitempty"` 23 | RevokedAt string `json:"revokedAt,omitempty"` 24 | TerminationAt string `json:"terminationAt,omitempty"` 25 | QuotaUsage int `json:"quotaUsage,omitempty"` 26 | QuotaUsageTimestamp string `json:"quotaUsageTimestamp,omitempty"` 27 | QuotaUpdateState string `json:"quotaUpdateState,omitempty"` 28 | } 29 | 30 | type CreateKey struct { 31 | Value string `json:"value,omitempty"` 32 | Label string `json:"label,omitempty"` 33 | Tags []string `json:"tags,omitempty"` 34 | CollectionId int `json:"collectionId,omitempty"` 35 | Description string `json:"description,omitempty"` 36 | Mode string `json:"mode,omitempty"` 37 | } 38 | 39 | func CollectionAddKey(collectionId int, name, value string) (*Key, error) { 40 | req, err := client.NewJSONRequest( 41 | Config, 42 | "POST", 43 | "/apikey-manager-api/v1/keys", 44 | &CreateKey{ 45 | Label: name, 46 | Value: value, 47 | CollectionId: collectionId, 48 | Mode: "CREATE_ONE", 49 | }, 50 | ) 51 | 52 | if err != nil { 53 | return nil, err 54 | } 55 | 56 | res, err := client.Do(Config, req) 57 | 58 | if err != nil { 59 | return nil, err 60 | } 61 | 62 | if client.IsError(res) { 63 | return nil, client.NewAPIError(res) 64 | } 65 | 66 | rep := &Key{} 67 | if err = client.BodyJSON(res, rep); err != nil { 68 | return nil, err 69 | } 70 | 71 | return rep, nil 72 | } 73 | 74 | type ImportKey struct { 75 | Name string `json:"name,omitempty"` 76 | Content string `json:"content,omitempty"` 77 | CollectionId int `json:"collectionId,omitempty"` 78 | } 79 | 80 | func CollectionImportKeys(collectionId int, filename string) (*Keys, error) { 81 | fileContent, err := ioutil.ReadFile(filename) 82 | if err != nil { 83 | return nil, err 84 | } 85 | 86 | req, err := client.NewJSONRequest( 87 | Config, 88 | "POST", 89 | "/apikey-manager-api/v1/keys/import", 90 | &ImportKey{ 91 | Name: filename, 92 | CollectionId: collectionId, 93 | Content: string(fileContent), 94 | }, 95 | ) 96 | 97 | if err != nil { 98 | return nil, err 99 | } 100 | 101 | res, err := client.Do(Config, req) 102 | 103 | if err != nil { 104 | return nil, err 105 | } 106 | 107 | if client.IsError(res) { 108 | return nil, client.NewAPIError(res) 109 | } 110 | 111 | rep := &Keys{} 112 | err = json.Unmarshal(fileContent, rep) 113 | 114 | return rep, err 115 | } 116 | 117 | type RevokeKeys struct { 118 | Keys Keys `json:"keys,omitempty"` 119 | } 120 | 121 | func RevokeKey(key int) (*Key, error) { 122 | req, err := client.NewJSONRequest( 123 | Config, 124 | "POST", 125 | "/apikey-manager-api/v1/keys/revoke", 126 | &RevokeKeys{ 127 | Keys: Keys{key}, 128 | }, 129 | ) 130 | 131 | if err != nil { 132 | return nil, err 133 | } 134 | 135 | res, err := client.Do(Config, req) 136 | 137 | if err != nil { 138 | return nil, err 139 | } 140 | 141 | if client.IsError(res) { 142 | return nil, client.NewAPIError(res) 143 | } 144 | 145 | return &Key{}, nil 146 | } 147 | -------------------------------------------------------------------------------- /api-endpoints-v2/versions.go: -------------------------------------------------------------------------------- 1 | package apiendpoints 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 7 | ) 8 | 9 | type Versions struct { 10 | APIEndPointID int `json:"apiEndPointId"` 11 | APIEndPointName string `json:"apiEndPointName"` 12 | APIVersions []Version `json:"apiVersions"` 13 | } 14 | 15 | type Version struct { 16 | CreatedBy string `json:"createdBy"` 17 | CreateDate string `json:"createDate"` 18 | UpdateDate string `json:"updateDate"` 19 | UpdatedBy string `json:"updatedBy"` 20 | APIEndPointVersionID int `json:"apiEndPointVersionId"` 21 | BasePath string `json:"basePath"` 22 | Description *string `json:"description` 23 | BasedOn *int `json:"basedOn"` 24 | StagingStatus *StatusValue `json:"stagingStatus"` 25 | ProductionStatus *StatusValue `json:"productionStatus"` 26 | StagingDate *string `json:"stagingDate"` 27 | ProductionDate *string `json:"productionDate"` 28 | IsVersionLocked bool `json:"isVersionLocked"` 29 | AvailableActions []string `json:"availableActions"` 30 | VersionNumber int `json:"versionNumber"` 31 | LockVersion int `json:"lockVersion"` 32 | } 33 | 34 | type VersionSummary struct { 35 | Status StatusValue `json:"status,omitempty"` 36 | VersionNumber int `json:"versionNumber,omitempty"` 37 | } 38 | 39 | type StatusValue string 40 | 41 | const ( 42 | StatusPending string = "PENDING" 43 | StatusActive string = "ACTIVE" 44 | StatusDeactivated string = "DEACTIVATED" 45 | StatusFailed string = "FAILED" 46 | ) 47 | 48 | type ListVersionsOptions struct { 49 | EndpointId int 50 | } 51 | 52 | func ListVersions(options *ListVersionsOptions) (*Versions, error) { 53 | req, err := client.NewJSONRequest( 54 | Config, 55 | "GET", 56 | fmt.Sprintf( 57 | "/api-definitions/v2/endpoints/%d/versions", 58 | options.EndpointId, 59 | ), 60 | nil, 61 | ) 62 | 63 | if err != nil { 64 | return nil, err 65 | } 66 | 67 | res, err := client.Do(Config, req) 68 | 69 | if client.IsError(res) { 70 | return nil, client.NewAPIError(res) 71 | } 72 | 73 | rep := &Versions{} 74 | if err = client.BodyJSON(res, rep); err != nil { 75 | return nil, err 76 | } 77 | 78 | return rep, nil 79 | } 80 | 81 | type GetVersionOptions struct { 82 | EndpointId int 83 | Version int 84 | } 85 | 86 | func GetVersion(options *GetVersionOptions) (*Endpoint, error) { 87 | if options.Version == 0 { 88 | versions, err := ListVersions(&ListVersionsOptions{EndpointId: options.EndpointId}) 89 | if err != nil { 90 | return nil, err 91 | } 92 | 93 | loc := len(versions.APIVersions) - 1 94 | v := versions.APIVersions[loc] 95 | options.Version = v.VersionNumber 96 | } 97 | 98 | req, err := client.NewJSONRequest( 99 | Config, 100 | "GET", 101 | fmt.Sprintf( 102 | "/api-definitions/v2/endpoints/%d/versions/%d/resources-detail", 103 | options.EndpointId, 104 | options.Version, 105 | ), 106 | nil, 107 | ) 108 | 109 | return call(req, err) 110 | } 111 | 112 | func ModifyVersion(endpoint *Endpoint) (*Endpoint, error) { 113 | req, err := client.NewJSONRequest( 114 | Config, 115 | "PUT", 116 | fmt.Sprintf( 117 | "/api-definitions/v2/endpoints/%d/versions/%d", 118 | endpoint.APIEndPointID, 119 | endpoint.VersionNumber, 120 | ), 121 | endpoint, 122 | ) 123 | 124 | return call(req, err) 125 | } 126 | 127 | type CloneVersionOptions struct { 128 | EndpointId int 129 | Version int 130 | } 131 | 132 | func CloneVersion(options *CloneVersionOptions) (*Endpoint, error) { 133 | req, err := client.NewJSONRequest( 134 | Config, 135 | "POST", 136 | fmt.Sprintf( 137 | "/api-definitions/v2/endpoints/%d/versions/%d/cloneVersion", 138 | options.EndpointId, 139 | options.Version, 140 | ), 141 | options, 142 | ) 143 | 144 | return call(req, err) 145 | } 146 | 147 | type RemoveVersionOptions struct { 148 | EndpointId int 149 | VersionNumber int 150 | } 151 | 152 | func RemoveVersion(options *RemoveVersionOptions) (*Endpoint, error) { 153 | req, err := client.NewJSONRequest( 154 | Config, 155 | "DELETE", 156 | fmt.Sprintf( 157 | "/api-definitions/v2/endpoints/%d/versions/%d", 158 | options.EndpointId, 159 | options.VersionNumber, 160 | ), 161 | nil, 162 | ) 163 | 164 | return call(req, err) 165 | } 166 | -------------------------------------------------------------------------------- /edgegrid/log.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018. Akamai Technologies, Inc 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package edgegrid 16 | 17 | import ( 18 | "bufio" 19 | "bytes" 20 | "encoding/json" 21 | "fmt" 22 | "net/http" 23 | "net/http/httputil" 24 | "os" 25 | "strings" 26 | 27 | logstd "log" 28 | 29 | log "github.com/sirupsen/logrus" 30 | ) 31 | 32 | var logBuffer *bufio.Writer 33 | var LogFile *os.File 34 | var EdgegridLog *log.Logger 35 | 36 | func SetupLogging() { 37 | 38 | if EdgegridLog != nil { 39 | return // already configured 40 | } 41 | 42 | EdgegridLog = log.New() 43 | EdgegridLog.SetFormatter(&log.TextFormatter{ 44 | DisableLevelTruncation: true, 45 | EnvironmentOverrideColors: true, 46 | }) 47 | // Log file destination specified? If not, use default stdout 48 | if logFileName := os.Getenv("AKAMAI_LOG_FILE"); logFileName != "" { 49 | // If the file doesn't exist, create it, or append to the file 50 | LogFile, err := os.OpenFile(logFileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) 51 | if err != nil { 52 | log.Fatal(err) 53 | } 54 | EdgegridLog.SetOutput(LogFile) 55 | } 56 | 57 | EdgegridLog.SetLevel(log.PanicLevel) 58 | if logLevel := os.Getenv("AKAMAI_LOG"); logLevel != "" { 59 | level, err := log.ParseLevel(logLevel) 60 | if err == nil { 61 | EdgegridLog.SetLevel(level) 62 | } else { 63 | log.Warningln("[WARN] Unknown AKAMAI_LOG value. Allowed values: panic, fatal, error, warn, info, debug, trace") 64 | 65 | } 66 | } 67 | 68 | defer LogFile.Close() 69 | } 70 | 71 | func LogMultiline(f func(args ...interface{}), args ...string) { 72 | for _, str := range args { 73 | for _, str := range strings.Split(strings.Trim(str, "\n"), "\n") { 74 | f(str) 75 | } 76 | } 77 | } 78 | 79 | func LogMultilineln(f func(args ...interface{}), args ...string) { 80 | LogMultiline(f, args...) 81 | } 82 | 83 | func LogMultilinef(f func(formatter string, args ...interface{}), formatter string, args ...interface{}) { 84 | str := fmt.Sprintf(formatter, args...) 85 | for _, str := range strings.Split(strings.Trim(str, "\n"), "\n") { 86 | f(str) 87 | } 88 | } 89 | 90 | // Utility func to print http req 91 | func PrintHttpRequest(req *http.Request, body bool) { 92 | 93 | if req == nil { 94 | return 95 | } 96 | b, err := httputil.DumpRequestOut(req, body) 97 | if err == nil { 98 | LogMultiline(EdgegridLog.Traceln, string(b)) 99 | } 100 | } 101 | 102 | func PrintHttpRequestCorrelation(req *http.Request, body bool, correlationid string) { 103 | 104 | if req == nil { 105 | return 106 | } 107 | b, err := httputil.DumpRequestOut(req, body) 108 | if err == nil { 109 | LogMultiline(EdgegridLog.Traceln, string(b)) 110 | PrintfCorrelation("[DEBUG] REQUEST", correlationid, prettyPrintJsonLines(b)) 111 | } 112 | } 113 | 114 | // Utility func to print http response 115 | func PrintHttpResponse(res *http.Response, body bool) { 116 | 117 | if res == nil { 118 | return 119 | } 120 | b, err := httputil.DumpResponse(res, body) 121 | if err == nil { 122 | LogMultiline(EdgegridLog.Traceln, string(b)) 123 | } 124 | } 125 | 126 | func PrintHttpResponseCorrelation(res *http.Response, body bool, correlationid string) { 127 | 128 | if res == nil { 129 | return 130 | } 131 | b, err := httputil.DumpResponse(res, body) 132 | if err == nil { 133 | LogMultiline(EdgegridLog.Traceln, string(b)) 134 | PrintfCorrelation("[DEBUG] RESPONSE ", correlationid, prettyPrintJsonLines(b)) 135 | } 136 | } 137 | 138 | func PrintfCorrelation(level string, correlationid string, msg string) { 139 | 140 | if correlationid == "" { 141 | logstd.Printf("%s %s\n", level, msg) 142 | } else { 143 | logstd.SetFlags(0) 144 | logstd.Printf("%v %s\n", correlationid, msg) 145 | } 146 | 147 | } 148 | 149 | // prettyPrintJsonLines iterates through a []byte line-by-line, 150 | // transforming any lines that are complete json into pretty-printed json. 151 | func prettyPrintJsonLines(b []byte) string { 152 | parts := strings.Split(string(b), "\n") 153 | for i, p := range parts { 154 | if b := []byte(p); json.Valid(b) { 155 | var out bytes.Buffer 156 | json.Indent(&out, b, "", " ") 157 | parts[i] = out.String() 158 | } 159 | } 160 | return strings.Join(parts, "\n") 161 | } 162 | -------------------------------------------------------------------------------- /papi-v1/contracts.go: -------------------------------------------------------------------------------- 1 | package papi 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | 7 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 8 | edge "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 9 | "github.com/patrickmn/go-cache" 10 | ) 11 | 12 | // Contracts represents a collection of property manager contracts 13 | type Contracts struct { 14 | client.Resource 15 | AccountID string `json:"accountId"` 16 | Contracts struct { 17 | Items []*Contract `json:"items"` 18 | } `json:"contracts"` 19 | } 20 | 21 | // NewContracts creates a new Contracts 22 | func NewContracts() *Contracts { 23 | contracts := &Contracts{} 24 | contracts.Init() 25 | return contracts 26 | } 27 | 28 | // PostUnmarshalJSON is called after JSON unmarshaling into EdgeHostnames 29 | // 30 | // See: jsonhooks-v1/jsonhooks.Unmarshal() 31 | func (contracts *Contracts) PostUnmarshalJSON() error { 32 | contracts.Init() 33 | 34 | for key, contract := range contracts.Contracts.Items { 35 | contracts.Contracts.Items[key].parent = contracts 36 | 37 | if err := contract.PostUnmarshalJSON(); err != nil { 38 | return err 39 | } 40 | } 41 | contracts.Complete <- true 42 | 43 | return nil 44 | } 45 | 46 | // GetContracts populates Contracts with contract data 47 | // 48 | // API Docs: https://developer.akamai.com/api/luna/papi/resources.html#listcontracts 49 | // Endpoint: GET /papi/v1/contracts 50 | func (contracts *Contracts) GetContracts(correlationid string) error { 51 | 52 | cachecontracts, found := Profilecache.Get("contracts") 53 | if found { 54 | json.Unmarshal(cachecontracts.([]byte), contracts) 55 | return nil 56 | } else { 57 | 58 | req, err := client.NewRequest( 59 | Config, 60 | "GET", 61 | "/papi/v1/contracts", 62 | nil, 63 | ) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | edge.PrintHttpRequestCorrelation(req, true, correlationid) 69 | 70 | res, err := client.Do(Config, req) 71 | if err != nil { 72 | return err 73 | } 74 | 75 | edge.PrintHttpResponseCorrelation(res, true, correlationid) 76 | 77 | if client.IsError(res) { 78 | return client.NewAPIError(res) 79 | } 80 | 81 | if err = client.BodyJSON(res, contracts); err != nil { 82 | return err 83 | } 84 | 85 | if err != nil { 86 | return err 87 | } 88 | byt, _ := json.Marshal(contracts) 89 | Profilecache.Set("contracts", byt, cache.DefaultExpiration) 90 | return nil 91 | } 92 | } 93 | 94 | // FindContract finds a specific contract by ID 95 | func (contracts *Contracts) FindContract(id string) (*Contract, error) { 96 | var contract *Contract 97 | var contractFound bool 98 | for _, contract = range contracts.Contracts.Items { 99 | if contract.ContractID == id { 100 | contractFound = true 101 | break 102 | } 103 | } 104 | 105 | if !contractFound { 106 | return nil, fmt.Errorf("Unable to find contract: \"%s\"", id) 107 | } 108 | 109 | return contract, nil 110 | } 111 | 112 | // Contract represents a property contract resource 113 | type Contract struct { 114 | client.Resource 115 | parent *Contracts 116 | ContractID string `json:"contractId"` 117 | ContractTypeName string `json:"contractTypeName"` 118 | } 119 | 120 | // NewContract creates a new Contract 121 | func NewContract(parent *Contracts) *Contract { 122 | contract := &Contract{ 123 | parent: parent, 124 | } 125 | contract.Init() 126 | return contract 127 | } 128 | 129 | // GetContract populates a Contract 130 | func (contract *Contract) GetContract() error { 131 | contracts, err := GetContracts() 132 | if err != nil { 133 | return err 134 | } 135 | 136 | for _, c := range contracts.Contracts.Items { 137 | if c.ContractID == contract.ContractID { 138 | contract.parent = c.parent 139 | contract.ContractTypeName = c.ContractTypeName 140 | contract.Complete <- true 141 | return nil 142 | } 143 | } 144 | contract.Complete <- false 145 | return fmt.Errorf("contract \"%s\" not found", contract.ContractID) 146 | } 147 | 148 | // GetProducts gets products associated with a contract 149 | func (contract *Contract) GetProducts() (*Products, error) { 150 | req, err := client.NewRequest( 151 | Config, 152 | "GET", 153 | fmt.Sprintf( 154 | "/papi/v1/products?contractId=%s", 155 | contract.ContractID, 156 | ), 157 | nil, 158 | ) 159 | if err != nil { 160 | return nil, err 161 | } 162 | 163 | edge.PrintHttpRequest(req, true) 164 | 165 | res, err := client.Do(Config, req) 166 | if err != nil { 167 | return nil, err 168 | } 169 | 170 | edge.PrintHttpResponse(res, true) 171 | 172 | if client.IsError(res) { 173 | return nil, client.NewAPIError(res) 174 | } 175 | 176 | products := NewProducts() 177 | if err = client.BodyJSON(res, products); err != nil { 178 | return nil, err 179 | } 180 | 181 | return products, nil 182 | } 183 | -------------------------------------------------------------------------------- /cps-v2/certificate_settings.go: -------------------------------------------------------------------------------- 1 | package cps 2 | 3 | type RegistrationAuthority string 4 | type CertificateType string 5 | type AkamaiCipher string 6 | type NetworkType string 7 | type OCSPSetting string 8 | type TLSType string 9 | type SHA string 10 | type ValidationType string 11 | 12 | const ( 13 | LetsEncryptRA RegistrationAuthority = "letsencrypt" 14 | SymantecRA RegistrationAuthority = "symantec" 15 | ThirdPartyRA RegistrationAuthority = "third-party" 16 | SanCertificate CertificateType = "san" 17 | SymantecCertificate CertificateType = "single" 18 | WildCardCertificate CertificateType = "wildcard" 19 | WildCardSanCertificate CertificateType = "wildcard-san" 20 | ThirdPartyCertificate CertificateType = "third-party" 21 | AK2018Q3 AkamaiCipher = "ak-akamai-2018q3" 22 | AK2017Q3 AkamaiCipher = "ak-akamai-default-2017q3" 23 | AK2016Q3 AkamaiCipher = "ak-akamai-default-2016q3" 24 | AKPCIDSS AkamaiCipher = "ak-pci-dss-3.2" 25 | AKDefault AkamaiCipher = "ak-akamai-default" 26 | AK2016Q1 AkamaiCipher = "ak-akamai-default-2016q1" 27 | AKPFSSupported AkamaiCipher = "ak-akamai-pfs-supported" 28 | AKPFS AkamaiCipher = "ak-akamai-pfs" 29 | AKRecommended AkamaiCipher = "ak-akamai-recommended" 30 | AKSoftErrors AkamaiCipher = "ak-soft-errors" 31 | AKSoftErrorsWithExport AkamaiCipher = "ak-soft-errors-with-export" 32 | AKTLS AkamaiCipher = "ak-akamai-tls-1.2" 33 | AKPCIDSSDefault AkamaiCipher = "ak-pci-dss" 34 | AKPCIDSS3 AkamaiCipher = "ak-pci-dss-3.1" 35 | StandardWorldWide NetworkType = "standard-worldwide" 36 | WorldWideRussia NetworkType = "worldwide-russia" 37 | WorldWide NetworkType = "worldwide" 38 | StandardTLS TLSType = "standard-tls" 39 | EnhancedTLS TLSType = "enhanced-tls" 40 | SHA1 SHA = "SHA-1" 41 | SHA256 SHA = "SHA-256" 42 | DomainValidation ValidationType = "dv" 43 | OrganizationValidation ValidationType = "ov" 44 | ExtendedValidation ValidationType = "ev" 45 | ThirdPartyValidation ValidationType = "third-party" 46 | ) 47 | 48 | type Contact struct { 49 | FirstName *string `json:"firstName"` 50 | LastName *string `json:"lastName"` 51 | Title *string `json:"title"` 52 | Organization *string `json:"organizationName"` 53 | Email *string `json:"email"` 54 | Phone *string `json:"phone"` 55 | AddressLineOne *string `json:"addressLineOne"` 56 | AddressLineTwo *string `json:"addressLineTwo"` 57 | City *string `json:"city"` 58 | Region *string `json:"region"` 59 | PostalCode *string `json:"postalCode"` 60 | Country *string `json:"country"` 61 | } 62 | 63 | type Organization struct { 64 | Name *string `json:"name"` 65 | Phone *string `json:"phone"` 66 | AddressLineOne *string `json:"addressLineOne"` 67 | AddressLineTwo *string `json:"addressLineTwo"` 68 | City *string `json:"city"` 69 | Region *string `json:"region"` 70 | PostalCode *string `json:"postalCode"` 71 | Country *string `json:"country"` 72 | } 73 | 74 | type CSR struct { 75 | CommonName string `json:"cn"` 76 | AlternativeNames *[]string `json:"sans"` 77 | City *string `json:"l"` 78 | State *string `json:"st"` 79 | CountryCode *string `json:"c"` 80 | Organization *string `json:"o"` 81 | OrganizationalUnit *string `json:"ou"` 82 | } 83 | 84 | type DomainNameSettings struct { 85 | CloneDomainNames bool `json:"cloneDnsNames"` 86 | DomainNames *[]string `json:"dnsNames"` 87 | } 88 | 89 | type NetworkConfiguration struct { 90 | DisallowedTLSVersions *[]string `json:"disallowedTlsVersions"` 91 | DomainNameSettings *DomainNameSettings `json:"dnsNameSettings"` 92 | Geography string `json:"geography"` 93 | MustHaveCiphers AkamaiCipher `json:"mustHaveCiphers"` 94 | // NetworkType *NetworkType `json:"networkType"` 95 | OCSPStapling *OCSPSetting `json:"ocspStapling"` 96 | PreferredCiphers AkamaiCipher `json:"preferredCiphers"` 97 | QUICEnabled bool `json:"quicEnabled"` 98 | SecureNetwork TLSType `json:"secureNetwork"` 99 | // ServerNameIndication *DomainNameSettings `json:"sni"` 100 | SNIOnly bool `json:"sniOnly"` 101 | } 102 | 103 | type ThirdParty struct { 104 | ExcludeSANS bool `json:"excludeSans"` 105 | } 106 | -------------------------------------------------------------------------------- /client-v1/client.go: -------------------------------------------------------------------------------- 1 | // Package client is a simple library for http.Client to sign Akamai OPEN Edgegrid API requests 2 | package client 3 | 4 | import ( 5 | "bytes" 6 | "errors" 7 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 8 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/jsonhooks-v1" 9 | "io" 10 | "io/ioutil" 11 | "mime/multipart" 12 | "net/http" 13 | "net/url" 14 | "os" 15 | "path/filepath" 16 | "runtime" 17 | "strings" 18 | "sync" 19 | ) 20 | 21 | var ( 22 | libraryVersion = "0.6.2" 23 | // UserAgent is the User-Agent value sent for all requests 24 | UserAgent = "Akamai-Open-Edgegrid-golang/" + libraryVersion + " golang/" + strings.TrimPrefix(runtime.Version(), "go") 25 | // Client is the *http.Client to use 26 | Client = http.DefaultClient 27 | 28 | reqLock sync.Mutex 29 | ) 30 | 31 | // NewRequest creates an HTTP request that can be sent to Akamai APIs. A relative URL can be provided in path, which will be resolved to the 32 | // Host specified in Config. If body is specified, it will be sent as the request body. 33 | func NewRequest(config edgegrid.Config, method, path string, body io.Reader) (*http.Request, error) { 34 | var ( 35 | baseURL *url.URL 36 | err error 37 | ) 38 | 39 | reqLock.Lock() 40 | defer reqLock.Unlock() 41 | 42 | if strings.HasPrefix(config.Host, "https://") { 43 | baseURL, err = url.Parse(config.Host) 44 | } else { 45 | baseURL, err = url.Parse("https://" + config.Host) 46 | } 47 | 48 | if err != nil { 49 | return nil, err 50 | } 51 | 52 | rel, err := url.Parse(strings.TrimPrefix(path, "/")) 53 | if err != nil { 54 | return nil, err 55 | } 56 | 57 | u := baseURL.ResolveReference(rel) 58 | if config.AccountKey != "" { 59 | q := u.Query() 60 | q.Add("accountSwitchKey", config.AccountKey) 61 | u.RawQuery = q.Encode() 62 | } 63 | 64 | req, err := http.NewRequest(method, u.String(), body) 65 | if err != nil { 66 | return nil, err 67 | } 68 | 69 | req.Header.Add("User-Agent", UserAgent) 70 | 71 | return req, nil 72 | } 73 | 74 | // NewJSONRequest creates an HTTP request that can be sent to the Akamai APIs with a JSON body 75 | // The JSON body is encoded and the Content-Type/Accept headers are set automatically. 76 | func NewJSONRequest(config edgegrid.Config, method, path string, body interface{}) (*http.Request, error) { 77 | var req *http.Request 78 | var err error 79 | 80 | if body != nil { 81 | jsonBody, err := jsonhooks.Marshal(body) 82 | if err != nil { 83 | return nil, err 84 | } 85 | buf := bytes.NewReader(jsonBody) 86 | req, err = NewRequest(config, method, path, buf) 87 | } else { 88 | req, err = NewRequest(config, method, path, nil) 89 | } 90 | 91 | if err != nil { 92 | return nil, err 93 | } 94 | 95 | req.Header.Set("Content-Type", "application/json") 96 | req.Header.Set("Accept", "application/json,*/*") 97 | 98 | return req, nil 99 | } 100 | 101 | // NewMultiPartFormDataRequest creates an HTTP request that uploads a file to the Akamai API 102 | func NewMultiPartFormDataRequest(config edgegrid.Config, uriPath, filePath string, otherFormParams map[string]string) (*http.Request, error) { 103 | file, err := os.Open(filePath) 104 | if err != nil { 105 | return nil, err 106 | } 107 | defer file.Close() 108 | 109 | body := &bytes.Buffer{} 110 | writer := multipart.NewWriter(body) 111 | // TODO: make this field name configurable 112 | part, err := writer.CreateFormFile("importFile", filepath.Base(filePath)) 113 | if err != nil { 114 | return nil, err 115 | } 116 | _, err = io.Copy(part, file) 117 | 118 | for key, val := range otherFormParams { 119 | _ = writer.WriteField(key, val) 120 | } 121 | err = writer.Close() 122 | if err != nil { 123 | return nil, err 124 | } 125 | 126 | req, err := NewRequest(config, "POST", uriPath, body) 127 | req.Header.Set("Content-Type", writer.FormDataContentType()) 128 | return req, err 129 | } 130 | 131 | // Do performs a given HTTP Request, signed with the Akamai OPEN Edgegrid 132 | // Authorization header. An edgegrid.Response or an error is returned. 133 | func Do(config edgegrid.Config, req *http.Request) (*http.Response, error) { 134 | Client.CheckRedirect = func(req *http.Request, via []*http.Request) error { 135 | req = edgegrid.AddRequestHeader(config, req) 136 | return nil 137 | } 138 | 139 | req = edgegrid.AddRequestHeader(config, req) 140 | res, err := Client.Do(req) 141 | if err != nil { 142 | return nil, err 143 | } 144 | 145 | return res, nil 146 | } 147 | 148 | // BodyJSON unmarshals the Response.Body into a given data structure 149 | func BodyJSON(r *http.Response, data interface{}) error { 150 | if data == nil { 151 | return errors.New("You must pass in an interface{}") 152 | } 153 | 154 | body, err := ioutil.ReadAll(r.Body) 155 | if err != nil { 156 | return err 157 | } 158 | err = jsonhooks.Unmarshal(body, data) 159 | 160 | return err 161 | } 162 | -------------------------------------------------------------------------------- /reportsgtm-v1/util.go: -------------------------------------------------------------------------------- 1 | package reportsgtm 2 | 3 | import ( 4 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 5 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/configgtm-v1_3" 6 | "net/http" 7 | 8 | "fmt" 9 | "time" 10 | ) 11 | 12 | // 13 | // Support gtm reports thru Edgegrid 14 | // Based on 1.0 Schema 15 | // 16 | 17 | type WindowResponse struct { 18 | StartTime time.Time 19 | EndTime time.Time 20 | } 21 | 22 | type APIWindowResponse struct { 23 | Start string `json:"start"` 24 | End string `json:"end"` 25 | } 26 | 27 | func setEncodedHeader(req *http.Request) { 28 | 29 | if req.Method == "GET" { 30 | req.Header.Set("Content-Type", "application/x-www-form-urlencoded") 31 | } 32 | 33 | return 34 | 35 | } 36 | 37 | // Utility method to convert an RFC3339 formated time string to a time.Time object 38 | func convertRFC3339toDate(rfc3339Stamp string) (time.Time, error) { 39 | 40 | t, err := time.Parse(time.RFC3339, rfc3339Stamp) 41 | return t, err 42 | 43 | } 44 | 45 | func createTimeWindow(apiResponse *APIWindowResponse) (*WindowResponse, error) { 46 | 47 | var err error 48 | windowResponse := &WindowResponse{} 49 | windowResponse.StartTime, err = convertRFC3339toDate(apiResponse.Start) 50 | if err != nil { 51 | return nil, err 52 | } 53 | windowResponse.EndTime, err = convertRFC3339toDate(apiResponse.End) 54 | if err != nil { 55 | return nil, err 56 | } 57 | return windowResponse, nil 58 | 59 | } 60 | 61 | // Core function to retrieve all Window API requests 62 | func getWindowCore(hostURL string) (*WindowResponse, error) { 63 | 64 | stat := &APIWindowResponse{} 65 | 66 | req, err := client.NewRequest( 67 | Config, 68 | "GET", 69 | hostURL, 70 | nil, 71 | ) 72 | if err != nil { 73 | return nil, err 74 | } 75 | 76 | printHttpRequest(req, true) 77 | 78 | res, err := client.Do(Config, req) 79 | if err != nil { 80 | return nil, err 81 | } 82 | 83 | printHttpResponse(res, true) 84 | 85 | if client.IsError(res) { 86 | if res.StatusCode == 400 { 87 | // Get the body. Could be bad dates. 88 | var windRespErrBody map[string]interface{} 89 | err = client.BodyJSON(res, windRespErrBody) 90 | if err != nil { 91 | return nil, err 92 | } 93 | // are available dates present? 94 | if availEnd, ok := windRespErrBody["availableEndDate"]; ok { 95 | stat.End = availEnd.(string) 96 | } 97 | if availStart, ok := windRespErrBody["availableStartDate"]; ok { 98 | stat.Start = availStart.(string) 99 | } 100 | if stat.End == "" || stat.Start == "" { 101 | cErr := configgtm.CommonError{} 102 | cErr.SetItem("entityName", "Window") 103 | cErr.SetItem("name", "Data Window") 104 | cErr.SetItem("apiErrorMessage", "No available data window") 105 | return nil, cErr 106 | } 107 | } else if res.StatusCode == 404 { 108 | cErr := configgtm.CommonError{} 109 | cErr.SetItem("entityName", "Window") 110 | cErr.SetItem("name", "Data Window") 111 | return nil, cErr 112 | } else { 113 | return nil, client.NewAPIError(res) 114 | } 115 | } else { 116 | err = client.BodyJSON(res, stat) 117 | if err != nil { 118 | return nil, err 119 | } 120 | } 121 | timeWindow, err := createTimeWindow(stat) 122 | if err != nil { 123 | return nil, err 124 | } 125 | return timeWindow, nil 126 | } 127 | 128 | // GetDemandWindow is a utility function that retrieves the data window for Demand category of Report APIs 129 | func GetDemandWindow(domainName string, propertyName string) (*WindowResponse, error) { 130 | 131 | hostURL := fmt.Sprintf("/gtm-api/v1/reports/demand/domains/%s/properties/%s/window", domainName, propertyName) 132 | return getWindowCore(hostURL) 133 | 134 | } 135 | 136 | // GetLatencyDomainsWindow is a utility function that retrieves the data window for Latency category of Report APIs 137 | func GetLatencyDomainsWindow(domainName string) (*WindowResponse, error) { 138 | 139 | hostURL := fmt.Sprintf("/gtm-api/v1/reports/latency/domains/%s/window", domainName) 140 | return getWindowCore(hostURL) 141 | 142 | } 143 | 144 | // GetLivenessTestsWindow is a utility function that retrieves the data window for Liveness category of Report APIs 145 | func GetLivenessTestsWindow() (*WindowResponse, error) { 146 | 147 | hostURL := fmt.Sprintf("/gtm-api/v1/reports/liveness-tests/window") 148 | return getWindowCore(hostURL) 149 | 150 | } 151 | 152 | // GetDatacentersTrafficWindow is a utility function that retrieves the data window for Traffic category of Report APIs 153 | func GetDatacentersTrafficWindow() (*WindowResponse, error) { 154 | 155 | hostURL := fmt.Sprintf("/gtm-api/v1/reports/traffic/datacenters-window") 156 | return getWindowCore(hostURL) 157 | 158 | } 159 | 160 | // GetPropertiesTrafficWindow is a utility function that retrieves the data window for Traffic category of Report API 161 | func GetPropertiesTrafficWindow() (*WindowResponse, error) { 162 | 163 | hostURL := fmt.Sprintf("/gtm-api/v1/reports/traffic/properties-window") 164 | return getWindowCore(hostURL) 165 | 166 | } 167 | -------------------------------------------------------------------------------- /edgegrid/config.go: -------------------------------------------------------------------------------- 1 | package edgegrid 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "strconv" 7 | "strings" 8 | 9 | "github.com/mitchellh/go-homedir" 10 | "gopkg.in/ini.v1" 11 | ) 12 | 13 | // Config struct provides all the necessary fields to 14 | // create authorization header, debug is optional 15 | type Config struct { 16 | Host string `ini:"host"` 17 | ClientToken string `ini:"client_token"` 18 | ClientSecret string `ini:"client_secret"` 19 | AccessToken string `ini:"access_token"` 20 | AccountKey string `ini:"account_key"` 21 | HeaderToSign []string `ini:"headers_to_sign"` 22 | MaxBody int `ini:"max_body"` 23 | Debug bool `ini:"debug"` 24 | } 25 | 26 | // Init initializes by first attempting to use ENV vars, with .edgerc as a fallback 27 | // 28 | // See: InitEnv() 29 | // See: InitEdgeRc() 30 | func Init(filepath string, section string) (Config, error) { 31 | if section == "" { 32 | section = defaultSection 33 | } else { 34 | section = strings.ToUpper(section) 35 | } 36 | 37 | _, exists := os.LookupEnv("AKAMAI_" + section + "_HOST") 38 | if !exists && section == defaultSection { 39 | _, exists := os.LookupEnv("AKAMAI_HOST") 40 | 41 | if exists { 42 | return InitEnv("") 43 | } 44 | } 45 | 46 | if exists { 47 | return InitEnv(section) 48 | } 49 | 50 | c, err := InitEdgeRc(filepath, strings.ToLower(section)) 51 | 52 | if err == nil { 53 | return c, nil 54 | } 55 | 56 | if section != defaultSection { 57 | _, ok := os.LookupEnv("AKAMAI_HOST") 58 | if ok { 59 | return InitEnv("") 60 | } 61 | } 62 | 63 | return c, fmt.Errorf("Unable to create instance using environment or .edgerc file") 64 | } 65 | 66 | // InitEdgeRc initializes using a configuration file in standard INI format 67 | // 68 | // By default, it uses the .edgerc found in the users home directory, and the 69 | // "default" section. 70 | func InitEdgeRc(filepath string, section string) (Config, error) { 71 | var ( 72 | c Config 73 | requiredOptions = []string{"host", "client_token", "client_secret", "access_token"} 74 | missing []string 75 | ) 76 | 77 | // Check if filepath is empty 78 | if filepath == "" { 79 | filepath = "~/.edgerc" 80 | } 81 | 82 | // Check if section is empty 83 | if section == "" { 84 | section = "default" 85 | } 86 | 87 | // Tilde seems to be not working when passing ~/.edgerc as file 88 | // Takes current user and use home dir instead 89 | 90 | path, err := homedir.Expand(filepath) 91 | 92 | if err != nil { 93 | return c, fmt.Errorf(errorMap[ErrHomeDirNotFound], err) 94 | } 95 | 96 | edgerc, err := ini.Load(path) 97 | if err != nil { 98 | return c, fmt.Errorf(errorMap[ErrConfigFile], err) 99 | } 100 | err = edgerc.Section(section).MapTo(&c) 101 | if err != nil { 102 | return c, fmt.Errorf(errorMap[ErrConfigFileSection], err) 103 | } 104 | for _, opt := range requiredOptions { 105 | if !(edgerc.Section(section).HasKey(opt)) { 106 | missing = append(missing, opt) 107 | } 108 | } 109 | if len(missing) > 0 { 110 | return c, fmt.Errorf(errorMap[ErrConfigMissingOptions], missing) 111 | } 112 | if c.MaxBody == 0 { 113 | c.MaxBody = 131072 114 | } 115 | return c, nil 116 | } 117 | 118 | // InitEnv initializes using the Environment (ENV) 119 | // 120 | // By default, it uses AKAMAI_HOST, AKAMAI_CLIENT_TOKEN, AKAMAI_CLIENT_SECRET, 121 | // AKAMAI_ACCESS_TOKEN, and AKAMAI_MAX_BODY variables. 122 | // 123 | // You can define multiple configurations by prefixing with the section name specified, e.g. 124 | // passing "ccu" will cause it to look for AKAMAI_CCU_HOST, etc. 125 | // 126 | // If AKAMAI_{SECTION} does not exist, it will fall back to just AKAMAI_. 127 | func InitEnv(section string) (Config, error) { 128 | var ( 129 | c Config 130 | requiredOptions = []string{"HOST", "CLIENT_TOKEN", "CLIENT_SECRET", "ACCESS_TOKEN"} 131 | missing []string 132 | prefix string 133 | ) 134 | 135 | // Check if section is empty 136 | if section == "" { 137 | section = defaultSection 138 | } else { 139 | section = strings.ToUpper(section) 140 | } 141 | 142 | prefix = "AKAMAI_" 143 | _, ok := os.LookupEnv("AKAMAI_" + section + "_HOST") 144 | if ok { 145 | prefix = "AKAMAI_" + section + "_" 146 | } 147 | 148 | for _, opt := range requiredOptions { 149 | val, ok := os.LookupEnv(prefix + opt) 150 | if !ok { 151 | missing = append(missing, prefix+opt) 152 | } else { 153 | switch { 154 | case opt == "HOST": 155 | c.Host = val 156 | case opt == "CLIENT_TOKEN": 157 | c.ClientToken = val 158 | case opt == "CLIENT_SECRET": 159 | c.ClientSecret = val 160 | case opt == "ACCESS_TOKEN": 161 | c.AccessToken = val 162 | } 163 | } 164 | } 165 | 166 | if len(missing) > 0 { 167 | return c, fmt.Errorf(errorMap[ErrMissingEnvVariables], missing) 168 | } 169 | 170 | c.MaxBody = 0 171 | 172 | val, ok := os.LookupEnv(prefix + "MAX_BODY") 173 | if i, err := strconv.Atoi(val); err == nil { 174 | c.MaxBody = i 175 | } 176 | 177 | if !ok || c.MaxBody == 0 { 178 | c.MaxBody = 131072 179 | } 180 | 181 | return c, nil 182 | } 183 | -------------------------------------------------------------------------------- /papi-v1/hostnames.go: -------------------------------------------------------------------------------- 1 | package papi 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 7 | edge "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 8 | ) 9 | 10 | // Hostnames is a collection of Property Hostnames 11 | type Hostnames struct { 12 | client.Resource 13 | AccountID string `json:"accountId"` 14 | ContractID string `json:"contractId"` 15 | GroupID string `json:"groupId"` 16 | PropertyID string `json:"propertyId"` 17 | PropertyVersion int `json:"propertyVersion"` 18 | Etag string `json:"etag"` 19 | Hostnames struct { 20 | Items []*Hostname `json:"items"` 21 | } `json:"hostnames"` 22 | } 23 | 24 | // NewHostnames creates a new Hostnames 25 | func NewHostnames() *Hostnames { 26 | hostnames := &Hostnames{} 27 | hostnames.Init() 28 | 29 | return hostnames 30 | } 31 | 32 | // PostUnmarshalJSON is called after JSON unmarshaling into EdgeHostnames 33 | // 34 | // See: jsonhooks-v1/jsonhooks.Unmarshal() 35 | func (hostnames *Hostnames) PostUnmarshalJSON() error { 36 | hostnames.Init() 37 | 38 | for key, hostname := range hostnames.Hostnames.Items { 39 | hostnames.Hostnames.Items[key].parent = hostnames 40 | if err := hostname.PostUnmarshalJSON(); err != nil { 41 | return err 42 | } 43 | } 44 | 45 | hostnames.Complete <- true 46 | 47 | return nil 48 | } 49 | 50 | // GetHostnames retrieves hostnames assigned to a given property 51 | // 52 | // If no version is given, the latest version is used 53 | // 54 | // See: Property.GetHostnames() 55 | // API Docs: https://developer.akamai.com/api/luna/papi/resources.html#listapropertyshostnames 56 | // Endpoint: GET /papi/v1/properties/{propertyId}/versions/{propertyVersion}/hostnames/{?contractId,groupId} 57 | func (hostnames *Hostnames) GetHostnames(version *Version, correlationid string) error { 58 | if version == nil { 59 | property := NewProperty(NewProperties()) 60 | property.PropertyID = hostnames.PropertyID 61 | err := property.GetProperty(correlationid) 62 | if err != nil { 63 | return err 64 | } 65 | 66 | version, err = property.GetLatestVersion("", correlationid) 67 | if err != nil { 68 | return err 69 | } 70 | } 71 | 72 | req, err := client.NewRequest( 73 | Config, 74 | "GET", 75 | fmt.Sprintf( 76 | "/papi/v1/properties/%s/versions/%d/hostnames/?contractId=%s&groupId=%s", 77 | hostnames.PropertyID, 78 | version.PropertyVersion, 79 | hostnames.ContractID, 80 | hostnames.GroupID, 81 | ), 82 | nil, 83 | ) 84 | if err != nil { 85 | return err 86 | } 87 | 88 | edge.PrintHttpRequestCorrelation(req, true, correlationid) 89 | 90 | res, err := client.Do(Config, req) 91 | if err != nil { 92 | return err 93 | } 94 | 95 | edge.PrintHttpResponseCorrelation(res, true, correlationid) 96 | 97 | if client.IsError(res) { 98 | return client.NewAPIError(res) 99 | } 100 | 101 | if err = client.BodyJSON(res, hostnames); err != nil { 102 | return err 103 | } 104 | 105 | return nil 106 | } 107 | 108 | // NewHostname creates a new Hostname within a given Hostnames 109 | func (hostnames *Hostnames) NewHostname() *Hostname { 110 | hostname := NewHostname(hostnames) 111 | hostnames.Hostnames.Items = append(hostnames.Hostnames.Items, hostname) 112 | return hostname 113 | } 114 | 115 | // Save updates a properties hostnames 116 | func (hostnames *Hostnames) Save() error { 117 | req, err := client.NewJSONRequest( 118 | Config, 119 | "PUT", 120 | fmt.Sprintf( 121 | "/papi/v1/properties/%s/versions/%d/hostnames?contractId=%s&groupId=%s", 122 | hostnames.PropertyID, 123 | hostnames.PropertyVersion, 124 | hostnames.ContractID, 125 | hostnames.GroupID, 126 | ), 127 | hostnames.Hostnames.Items, 128 | ) 129 | if err != nil { 130 | return err 131 | } 132 | 133 | edge.PrintHttpRequest(req, true) 134 | 135 | res, err := client.Do(Config, req) 136 | if err != nil { 137 | return err 138 | } 139 | 140 | edge.PrintHttpResponse(res, true) 141 | 142 | if client.IsError(res) { 143 | return client.NewAPIError(res) 144 | } 145 | 146 | if err = client.BodyJSON(res, hostnames); err != nil { 147 | return err 148 | } 149 | 150 | return nil 151 | } 152 | 153 | // Hostname represents a property hostname resource 154 | type Hostname struct { 155 | client.Resource 156 | parent *Hostnames 157 | CnameType CnameTypeValue `json:"cnameType"` 158 | EdgeHostnameID string `json:"edgeHostnameId,omitempty"` 159 | CnameFrom string `json:"cnameFrom"` 160 | CnameTo string `json:"cnameTo,omitempty"` 161 | CertEnrollmentId string `json:"certEnrollmentId,omitempty"` 162 | } 163 | 164 | // NewHostname creates a new Hostname 165 | func NewHostname(parent *Hostnames) *Hostname { 166 | hostname := &Hostname{parent: parent, CnameType: CnameTypeEdgeHostname} 167 | hostname.Init() 168 | 169 | return hostname 170 | } 171 | 172 | // CnameTypeValue is used to create an "enum" of possible Hostname.CnameType values 173 | type CnameTypeValue string 174 | 175 | const ( 176 | // CnameTypeEdgeHostname Hostname.CnameType value EDGE_HOSTNAME 177 | CnameTypeEdgeHostname CnameTypeValue = "EDGE_HOSTNAME" 178 | ) 179 | -------------------------------------------------------------------------------- /papi-v1/custombehaviors.go: -------------------------------------------------------------------------------- 1 | package papi 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 8 | edge "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 9 | ) 10 | 11 | // CustomBehaviors represents a collection of Custom Behaviors 12 | // 13 | // See: CustomBehaviors.GetCustomBehaviors() 14 | // API Docs: https://developer.akamai.com/api/luna/papi/data.html#custombehavior 15 | type CustomBehaviors struct { 16 | client.Resource 17 | AccountID string `json:"accountId"` 18 | CustomBehaviors struct { 19 | Items []*CustomBehavior `json:"items"` 20 | } `json:"customBehaviors"` 21 | } 22 | 23 | // NewCustomBehaviors creates a new *CustomBehaviors 24 | func NewCustomBehaviors() *CustomBehaviors { 25 | return &CustomBehaviors{} 26 | } 27 | 28 | // PostUnmarshalJSON is called after UnmarshalJSON to setup the 29 | // structs internal state. The cpcodes.Complete channel is utilized 30 | // to communicate full completion. 31 | func (behaviors *CustomBehaviors) PostUnmarshalJSON() error { 32 | behaviors.Init() 33 | 34 | for key, behavior := range behaviors.CustomBehaviors.Items { 35 | behaviors.CustomBehaviors.Items[key].parent = behaviors 36 | 37 | if err := behavior.PostUnmarshalJSON(); err != nil { 38 | return err 39 | } 40 | } 41 | 42 | return nil 43 | } 44 | 45 | // GetCustomBehaviors populates a *CustomBehaviors with it's related Custom Behaviors 46 | // 47 | // API Docs: https://developer.akamai.com/api/luna/papi/resources.html#getcustombehaviors 48 | // Endpoint: GET /papi/v1/custom-behaviors 49 | func (behaviors *CustomBehaviors) GetCustomBehaviors() error { 50 | req, err := client.NewRequest( 51 | Config, 52 | "GET", 53 | "/papi/v1/custom-behaviors", 54 | nil, 55 | ) 56 | if err != nil { 57 | return err 58 | } 59 | 60 | edge.PrintHttpRequest(req, true) 61 | 62 | res, err := client.Do(Config, req) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | edge.PrintHttpResponse(res, true) 68 | 69 | if client.IsError(res) { 70 | return client.NewAPIError(res) 71 | } 72 | 73 | if err = client.BodyJSON(res, behaviors); err != nil { 74 | return err 75 | } 76 | 77 | return nil 78 | } 79 | 80 | func (behaviors *CustomBehaviors) AddCustomBehavior(behavior *CustomBehavior) { 81 | var exists bool 82 | for _, cb := range behaviors.CustomBehaviors.Items { 83 | if cb == behavior { 84 | exists = true 85 | } 86 | } 87 | 88 | if !exists { 89 | behaviors.CustomBehaviors.Items = append(behaviors.CustomBehaviors.Items, behavior) 90 | } 91 | } 92 | 93 | // CustomBehavior represents a single Custom Behavior 94 | // 95 | // API Docs: https://developer.akamai.com/api/luna/papi/data.html#custombehavior 96 | type CustomBehavior struct { 97 | client.Resource 98 | parent *CustomBehaviors 99 | BehaviorID string `json:"behaviorId,omitempty"` 100 | Description string `json:"description"` 101 | DisplayName string `json:"displayName"` 102 | Name string `json:"name"` 103 | Status string `json:"status",omitempty` 104 | UpdatedByUser string `json:"updatedByUser,omitempty"` 105 | UpdatedDate time.Time `json:"updatedDate,omitempty"` 106 | XML string `json:"xml,omitempty"` 107 | } 108 | 109 | // GetCustomBehavior populates the *CustomBehavior with it's data 110 | // 111 | // API Docs: https://developer.akamai.com/api/luna/papi/resources.html#getcustombehavior 112 | // Endpoint: GET /papi/v1/custom-behaviors/{behaviorId} 113 | func (behavior *CustomBehavior) GetCustomBehavior() error { 114 | req, err := client.NewRequest( 115 | Config, 116 | "GET", 117 | fmt.Sprintf( 118 | "/papi/v1/custom-behaviors/%s", 119 | behavior.BehaviorID, 120 | ), 121 | nil, 122 | ) 123 | if err != nil { 124 | return err 125 | } 126 | 127 | edge.PrintHttpRequest(req, true) 128 | 129 | res, err := client.Do(Config, req) 130 | 131 | if err != nil { 132 | return err 133 | } 134 | 135 | edge.PrintHttpResponse(res, true) 136 | 137 | if client.IsError(res) { 138 | return client.NewAPIError(res) 139 | } 140 | 141 | newCustomBehaviors := NewCustomBehaviors() 142 | if err = client.BodyJSON(res, newCustomBehaviors); err != nil { 143 | return err 144 | } 145 | if len(newCustomBehaviors.CustomBehaviors.Items) == 0 { 146 | return fmt.Errorf("Custom Behavior \"%s\" not found", behavior.BehaviorID) 147 | } 148 | 149 | behavior.Name = newCustomBehaviors.CustomBehaviors.Items[0].Name 150 | behavior.Description = newCustomBehaviors.CustomBehaviors.Items[0].Description 151 | behavior.DisplayName = newCustomBehaviors.CustomBehaviors.Items[0].DisplayName 152 | behavior.Status = newCustomBehaviors.CustomBehaviors.Items[0].Status 153 | behavior.UpdatedByUser = newCustomBehaviors.CustomBehaviors.Items[0].UpdatedByUser 154 | behavior.UpdatedDate = newCustomBehaviors.CustomBehaviors.Items[0].UpdatedDate 155 | behavior.XML = newCustomBehaviors.CustomBehaviors.Items[0].XML 156 | 157 | behavior.parent.AddCustomBehavior(behavior) 158 | 159 | return nil 160 | } 161 | 162 | // NewCustomBehavior creates a new *CustomBehavior 163 | func NewCustomBehavior(behaviors *CustomBehaviors) *CustomBehavior { 164 | return &CustomBehavior{parent: behaviors} 165 | } 166 | -------------------------------------------------------------------------------- /papi-v1/customoverrides.go: -------------------------------------------------------------------------------- 1 | package papi 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 8 | edge "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 9 | ) 10 | 11 | // CustomOverrides represents a collection of Custom Overrides 12 | // 13 | // See: CustomerOverrides.GetCustomOverrides() 14 | // API Docs: https://developer.akamai.com/api/luna/papi/data.html#cpcode 15 | type CustomOverrides struct { 16 | client.Resource 17 | AccountID string `json:"accountId"` 18 | CustomOverrides struct { 19 | Items []*CustomOverride `json:"items"` 20 | } `json:"customOverrides"` 21 | } 22 | 23 | // NewCustomOverrides creates a new *CustomOverrides 24 | func NewCustomOverrides() *CustomOverrides { 25 | return &CustomOverrides{} 26 | } 27 | 28 | // PostUnmarshalJSON is called after UnmarshalJSON to setup the 29 | // structs internal state. The CustomOverrides.Complete channel is utilized 30 | // to communicate full completion. 31 | func (overrides *CustomOverrides) PostUnmarshalJSON() error { 32 | overrides.Init() 33 | 34 | for key, override := range overrides.CustomOverrides.Items { 35 | overrides.CustomOverrides.Items[key].parent = overrides 36 | 37 | if err := override.PostUnmarshalJSON(); err != nil { 38 | return err 39 | } 40 | } 41 | 42 | overrides.Complete <- true 43 | 44 | return nil 45 | } 46 | 47 | // GetCustomOverrides populates a *CustomOverrides with it's related Custom Overrides 48 | // 49 | // API Docs: https://developer.akamai.com/api/luna/papi/resources.html#getcustomoverrides 50 | // Endpoint: GET /papi/v1/custom-overrides 51 | func (overrides *CustomOverrides) GetCustomOverrides() error { 52 | req, err := client.NewRequest( 53 | Config, 54 | "GET", 55 | "/papi/v1/custom-overrides", 56 | nil, 57 | ) 58 | if err != nil { 59 | return err 60 | } 61 | 62 | edge.PrintHttpRequest(req, true) 63 | 64 | res, err := client.Do(Config, req) 65 | if err != nil { 66 | return err 67 | } 68 | 69 | edge.PrintHttpResponse(res, true) 70 | 71 | if client.IsError(res) { 72 | return client.NewAPIError(res) 73 | } 74 | 75 | if err = client.BodyJSON(res, overrides); err != nil { 76 | return err 77 | } 78 | 79 | return nil 80 | } 81 | 82 | func (overrides *CustomOverrides) AddCustomOverride(override *CustomOverride) { 83 | var exists bool 84 | for _, co := range overrides.CustomOverrides.Items { 85 | if co == override { 86 | exists = true 87 | } 88 | } 89 | 90 | if !exists { 91 | overrides.CustomOverrides.Items = append(overrides.CustomOverrides.Items, override) 92 | } 93 | } 94 | 95 | // CustomOverride represents a single Custom Override 96 | // 97 | // API Docs: https://developer.akamai.com/api/luna/papi/data.html#customoverride 98 | type CustomOverride struct { 99 | client.Resource 100 | parent *CustomOverrides 101 | Description string `json:"description"` 102 | DisplayName string `json:"displayName"` 103 | Name string `json:"name"` 104 | OverrideID string `json:"overrideId,omitempty"` 105 | Status string `json:"status",omitempty` 106 | UpdatedByUser string `json:"updatedByUser,omitempty"` 107 | UpdatedDate time.Time `json:"updatedDate,omitempty"` 108 | XML string `json:"xml,omitempty"` 109 | } 110 | 111 | // GetCustomOverride populates the *CustomOverride with it's data 112 | // 113 | // API Docs: https://developer.akamai.com/api/luna/papi/resources.html#getcustomoverride 114 | // Endpoint: GET /papi/v1/custom-overrides/{overrideId} 115 | func (override *CustomOverride) GetCustomOverride() error { 116 | req, err := client.NewRequest( 117 | Config, 118 | "GET", 119 | fmt.Sprintf( 120 | "/papi/v1/custom-overrides/%s", 121 | override.OverrideID, 122 | ), 123 | nil, 124 | ) 125 | if err != nil { 126 | return err 127 | } 128 | 129 | edge.PrintHttpRequest(req, true) 130 | 131 | res, err := client.Do(Config, req) 132 | if err != nil { 133 | return err 134 | } 135 | 136 | edge.PrintHttpResponse(res, true) 137 | 138 | if client.IsError(res) { 139 | return client.NewAPIError(res) 140 | } 141 | 142 | newCustomOverrides := NewCustomOverrides() 143 | if err = client.BodyJSON(res, newCustomOverrides); err != nil { 144 | return err 145 | } 146 | if len(newCustomOverrides.CustomOverrides.Items) == 0 { 147 | return fmt.Errorf("Custom Override \"%s\" not found", override.OverrideID) 148 | } 149 | 150 | override.Name = newCustomOverrides.CustomOverrides.Items[0].Name 151 | override.Description = newCustomOverrides.CustomOverrides.Items[0].Description 152 | override.DisplayName = newCustomOverrides.CustomOverrides.Items[0].DisplayName 153 | override.Status = newCustomOverrides.CustomOverrides.Items[0].Status 154 | override.UpdatedByUser = newCustomOverrides.CustomOverrides.Items[0].UpdatedByUser 155 | override.UpdatedDate = newCustomOverrides.CustomOverrides.Items[0].UpdatedDate 156 | override.XML = newCustomOverrides.CustomOverrides.Items[0].XML 157 | 158 | override.parent.AddCustomOverride(override) 159 | 160 | return nil 161 | } 162 | 163 | // NewCustomOverride creates a new *CustomOverride 164 | func NewCustomOverride(overrides *CustomOverrides) *CustomOverride { 165 | return &CustomOverride{parent: overrides} 166 | } 167 | -------------------------------------------------------------------------------- /configgtm-v1_4/asmap.go: -------------------------------------------------------------------------------- 1 | package configgtm 2 | 3 | import ( 4 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 5 | 6 | "fmt" 7 | ) 8 | 9 | // 10 | // Handle Operations on gtm asmaps 11 | // Based on 1.4 schema 12 | // 13 | 14 | // AsAssignment represents a GTM asmap assignment structure 15 | type AsAssignment struct { 16 | DatacenterBase 17 | AsNumbers []int64 `json:"asNumbers"` 18 | } 19 | 20 | // AsMap represents a GTM AsMap 21 | type AsMap struct { 22 | DefaultDatacenter *DatacenterBase `json:"defaultDatacenter"` 23 | Assignments []*AsAssignment `json:"assignments,omitempty"` 24 | Name string `json:"name"` 25 | Links []*Link `json:"links,omitempty"` 26 | } 27 | 28 | // NewAsMap creates a new asMap 29 | func NewAsMap(name string) *AsMap { 30 | asmap := &AsMap{Name: name} 31 | return asmap 32 | } 33 | 34 | // GetAsMap retrieves a asMap with the given name. 35 | func GetAsMap(name, domainName string) (*AsMap, error) { 36 | as := NewAsMap(name) 37 | req, err := client.NewRequest( 38 | Config, 39 | "GET", 40 | fmt.Sprintf("/config-gtm/v1/domains/%s/as-maps/%s", domainName, name), 41 | nil, 42 | ) 43 | if err != nil { 44 | return nil, err 45 | } 46 | 47 | setVersionHeader(req, schemaVersion) 48 | 49 | printHttpRequest(req, true) 50 | 51 | res, err := client.Do(Config, req) 52 | if err != nil { 53 | return nil, err 54 | } 55 | 56 | printHttpResponse(res, true) 57 | 58 | if client.IsError(res) && res.StatusCode != 404 { 59 | return nil, client.NewAPIError(res) 60 | } else if res.StatusCode == 404 { 61 | return nil, CommonError{entityName: "asMap", name: name} 62 | } else { 63 | err = client.BodyJSON(res, as) 64 | if err != nil { 65 | return nil, err 66 | } 67 | 68 | return as, nil 69 | } 70 | } 71 | 72 | // Instantiate new Assignment struct 73 | func (as *AsMap) NewAssignment(dcID int, nickname string) *AsAssignment { 74 | asAssign := &AsAssignment{} 75 | asAssign.DatacenterId = dcID 76 | asAssign.Nickname = nickname 77 | 78 | return asAssign 79 | 80 | } 81 | 82 | // Instantiate new Default Datacenter Struct 83 | func (as *AsMap) NewDefaultDatacenter(dcID int) *DatacenterBase { 84 | return &DatacenterBase{DatacenterId: dcID} 85 | } 86 | 87 | // Create asMap in provided domain 88 | func (as *AsMap) Create(domainName string) (*AsMapResponse, error) { 89 | 90 | // Use common code. Any specific validation needed? 91 | 92 | return as.save(domainName) 93 | 94 | } 95 | 96 | // Update AsMap in given domain 97 | func (as *AsMap) Update(domainName string) (*ResponseStatus, error) { 98 | 99 | // common code 100 | 101 | stat, err := as.save(domainName) 102 | if err != nil { 103 | return nil, err 104 | } 105 | return stat.Status, err 106 | 107 | } 108 | 109 | // Save AsMap in given domain. Common path for Create and Update. 110 | func (as *AsMap) save(domainName string) (*AsMapResponse, error) { 111 | 112 | req, err := client.NewJSONRequest( 113 | Config, 114 | "PUT", 115 | fmt.Sprintf("/config-gtm/v1/domains/%s/as-maps/%s", domainName, as.Name), 116 | as, 117 | ) 118 | if err != nil { 119 | return nil, err 120 | } 121 | 122 | setVersionHeader(req, schemaVersion) 123 | 124 | printHttpRequest(req, true) 125 | 126 | res, err := client.Do(Config, req) 127 | 128 | // Network error 129 | if err != nil { 130 | return nil, CommonError{ 131 | entityName: "asMap", 132 | name: as.Name, 133 | httpErrorMessage: err.Error(), 134 | err: err, 135 | } 136 | } 137 | 138 | printHttpResponse(res, true) 139 | 140 | // API error 141 | if client.IsError(res) { 142 | err := client.NewAPIError(res) 143 | return nil, CommonError{entityName: "asMap", name: as.Name, apiErrorMessage: err.Detail, err: err} 144 | } 145 | 146 | responseBody := &AsMapResponse{} 147 | // Unmarshall whole response body for updated entity and in case want status 148 | err = client.BodyJSON(res, responseBody) 149 | if err != nil { 150 | return nil, err 151 | } 152 | 153 | return responseBody, nil 154 | } 155 | 156 | // Delete AsMap method 157 | func (as *AsMap) Delete(domainName string) (*ResponseStatus, error) { 158 | 159 | req, err := client.NewRequest( 160 | Config, 161 | "DELETE", 162 | fmt.Sprintf("/config-gtm/v1/domains/%s/as-maps/%s", domainName, as.Name), 163 | nil, 164 | ) 165 | if err != nil { 166 | return nil, err 167 | } 168 | 169 | setVersionHeader(req, schemaVersion) 170 | 171 | printHttpRequest(req, true) 172 | 173 | res, err := client.Do(Config, req) 174 | if err != nil { 175 | return nil, err 176 | } 177 | 178 | // Network error 179 | if err != nil { 180 | return nil, CommonError{ 181 | entityName: "asMap", 182 | name: as.Name, 183 | httpErrorMessage: err.Error(), 184 | err: err, 185 | } 186 | } 187 | 188 | printHttpResponse(res, true) 189 | 190 | // API error 191 | if client.IsError(res) { 192 | err := client.NewAPIError(res) 193 | return nil, CommonError{entityName: "asMap", name: as.Name, apiErrorMessage: err.Detail, err: err} 194 | } 195 | 196 | responseBody := &ResponseBody{} 197 | // Unmarshall whole response body in case want status 198 | err = client.BodyJSON(res, responseBody) 199 | if err != nil { 200 | return nil, err 201 | } 202 | 203 | return responseBody.Status, nil 204 | } 205 | -------------------------------------------------------------------------------- /configgtm-v1_3/asmap.go: -------------------------------------------------------------------------------- 1 | package configgtm 2 | 3 | import ( 4 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 5 | 6 | "fmt" 7 | ) 8 | 9 | // 10 | // Handle Operations on gtm asmaps 11 | // Based on 1.3 schema 12 | // 13 | 14 | // AsAssignment represents a GTM asmap assignment structure 15 | type AsAssignment struct { 16 | DatacenterBase 17 | AsNumbers []int64 `json:"asNumbers,omitempty"` 18 | } 19 | 20 | // AsMap represents a GTM AsMap 21 | type AsMap struct { 22 | DefaultDatacenter *DatacenterBase `json:"defaultDatacenter"` 23 | Assignments []*AsAssignment `json:"assignments,omitempty"` 24 | Name string `json:"name"` 25 | Links []*Link `json:"links,omitempty"` 26 | } 27 | 28 | // NewAsMap creates a new asMap 29 | func NewAsMap(name string) *AsMap { 30 | asmap := &AsMap{Name: name} 31 | return asmap 32 | } 33 | 34 | // GetAsMap retrieves a asMap with the given name. 35 | func GetAsMap(name, domainName string) (*AsMap, error) { 36 | as := NewAsMap(name) 37 | req, err := client.NewRequest( 38 | Config, 39 | "GET", 40 | fmt.Sprintf("/config-gtm/v1/domains/%s/as-maps/%s", domainName, name), 41 | nil, 42 | ) 43 | if err != nil { 44 | return nil, err 45 | } 46 | 47 | setVersionHeader(req, schemaVersion) 48 | 49 | printHttpRequest(req, true) 50 | 51 | res, err := client.Do(Config, req) 52 | if err != nil { 53 | return nil, err 54 | } 55 | 56 | printHttpResponse(res, true) 57 | 58 | if client.IsError(res) && res.StatusCode != 404 { 59 | return nil, client.NewAPIError(res) 60 | } else if res.StatusCode == 404 { 61 | return nil, CommonError{entityName: "asMap", name: name} 62 | } else { 63 | err = client.BodyJSON(res, as) 64 | if err != nil { 65 | return nil, err 66 | } 67 | 68 | return as, nil 69 | } 70 | } 71 | 72 | // Instantiate new Assignment struct 73 | func (as *AsMap) NewAssignment(dcID int, nickname string) *AsAssignment { 74 | asAssign := &AsAssignment{} 75 | asAssign.DatacenterId = dcID 76 | asAssign.Nickname = nickname 77 | 78 | return asAssign 79 | 80 | } 81 | 82 | // Instantiate new Default Datacenter Struct 83 | func (as *AsMap) NewDefaultDatacenter(dcID int) *DatacenterBase { 84 | return &DatacenterBase{DatacenterId: dcID} 85 | } 86 | 87 | // Create asMap in provided domain 88 | func (as *AsMap) Create(domainName string) (*AsMapResponse, error) { 89 | 90 | // Use common code. Any specific validation needed? 91 | 92 | return as.save(domainName) 93 | 94 | } 95 | 96 | // Update AsMap in given domain 97 | func (as *AsMap) Update(domainName string) (*ResponseStatus, error) { 98 | 99 | // common code 100 | 101 | stat, err := as.save(domainName) 102 | if err != nil { 103 | return nil, err 104 | } 105 | return stat.Status, err 106 | 107 | } 108 | 109 | // Save AsMap in given domain. Common path for Create and Update. 110 | func (as *AsMap) save(domainName string) (*AsMapResponse, error) { 111 | 112 | req, err := client.NewJSONRequest( 113 | Config, 114 | "PUT", 115 | fmt.Sprintf("/config-gtm/v1/domains/%s/as-maps/%s", domainName, as.Name), 116 | as, 117 | ) 118 | if err != nil { 119 | return nil, err 120 | } 121 | 122 | setVersionHeader(req, schemaVersion) 123 | 124 | printHttpRequest(req, true) 125 | 126 | res, err := client.Do(Config, req) 127 | 128 | // Network error 129 | if err != nil { 130 | return nil, CommonError{ 131 | entityName: "asMap", 132 | name: as.Name, 133 | httpErrorMessage: err.Error(), 134 | err: err, 135 | } 136 | } 137 | 138 | printHttpResponse(res, true) 139 | 140 | // API error 141 | if client.IsError(res) { 142 | err := client.NewAPIError(res) 143 | return nil, CommonError{entityName: "asMap", name: as.Name, apiErrorMessage: err.Detail, err: err} 144 | } 145 | 146 | responseBody := &AsMapResponse{} 147 | // Unmarshall whole response body for updated entity and in case want status 148 | err = client.BodyJSON(res, responseBody) 149 | if err != nil { 150 | return nil, err 151 | } 152 | 153 | return responseBody, nil 154 | } 155 | 156 | // Delete AsMap method 157 | func (as *AsMap) Delete(domainName string) (*ResponseStatus, error) { 158 | 159 | req, err := client.NewRequest( 160 | Config, 161 | "DELETE", 162 | fmt.Sprintf("/config-gtm/v1/domains/%s/as-maps/%s", domainName, as.Name), 163 | nil, 164 | ) 165 | if err != nil { 166 | return nil, err 167 | } 168 | 169 | setVersionHeader(req, schemaVersion) 170 | 171 | printHttpRequest(req, true) 172 | 173 | res, err := client.Do(Config, req) 174 | if err != nil { 175 | return nil, err 176 | } 177 | 178 | // Network error 179 | if err != nil { 180 | return nil, CommonError{ 181 | entityName: "asMap", 182 | name: as.Name, 183 | httpErrorMessage: err.Error(), 184 | err: err, 185 | } 186 | } 187 | 188 | printHttpResponse(res, true) 189 | 190 | // API error 191 | if client.IsError(res) { 192 | err := client.NewAPIError(res) 193 | return nil, CommonError{entityName: "asMap", name: as.Name, apiErrorMessage: err.Detail, err: err} 194 | } 195 | 196 | responseBody := &ResponseBody{} 197 | // Unmarshall whole response body in case want status 198 | err = client.BodyJSON(res, responseBody) 199 | if err != nil { 200 | return nil, err 201 | } 202 | 203 | return responseBody.Status, nil 204 | } 205 | -------------------------------------------------------------------------------- /jsonhooks-v1/jsonhooks_test.go: -------------------------------------------------------------------------------- 1 | package jsonhooks 2 | 3 | import ( 4 | "encoding/json" 5 | "strings" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | type Optionals struct { 12 | Sr string `json:"sr"` 13 | So string `json:"so,omitempty"` 14 | Sw string `json:"-"` 15 | 16 | Ir int `json:"omitempty"` // actually named omitempty, not an option 17 | Io int `json:"io,omitempty"` 18 | 19 | Slr []string `json:"slr,random"` 20 | Slo []string `json:"slo,omitempty"` 21 | 22 | Mr map[string]interface{} `json:"mr"` 23 | Mo map[string]interface{} `json:",omitempty"` 24 | 25 | Fr float64 `json:"fr"` 26 | Fo float64 `json:"fo,omitempty"` 27 | 28 | Br bool `json:"br"` 29 | Bo bool `json:"bo,omitempty"` 30 | 31 | Ur uint `json:"ur"` 32 | Uo uint `json:"uo,omitempty"` 33 | 34 | Str struct{} `json:"str"` 35 | Sto struct{} `json:"sto,omitempty"` 36 | } 37 | 38 | type MixedTypes struct { 39 | I int `json:"I"` 40 | B bool `json:"B"` 41 | F float64 `json:"F"` 42 | S string `json:"S"` 43 | St struct { 44 | Foo int `json:"Foo"` 45 | Bar string `json:"Bar"` 46 | } `json:"St"` 47 | A []string `json:"A"` 48 | } 49 | 50 | type WithHooks MixedTypes 51 | 52 | func (hooks *WithHooks) PreMarshalJSON() error { 53 | hooks.I *= 1000 54 | hooks.B = !hooks.B 55 | hooks.F *= 1.1 56 | hooks.S = strings.ToUpper(hooks.S) 57 | hooks.St.Foo *= 2000 58 | hooks.St.Bar = strings.ToUpper(hooks.St.Bar) 59 | for key, val := range hooks.A { 60 | hooks.A[key] = strings.ToUpper(val) 61 | } 62 | 63 | return nil 64 | } 65 | 66 | func (hooks *WithHooks) PostUnmarshalJSON() error { 67 | hooks.I /= 1000 68 | hooks.B = !hooks.B 69 | hooks.F /= 1.1 70 | hooks.S = strings.ToLower(hooks.S) 71 | hooks.St.Foo /= 2000 72 | hooks.St.Bar = strings.ToLower(hooks.St.Bar) 73 | for key, val := range hooks.A { 74 | hooks.A[key] = strings.ToLower(val) 75 | } 76 | 77 | return nil 78 | } 79 | 80 | func TestMarshalCompat(t *testing.T) { 81 | var o Optionals 82 | o.Sw = "something" 83 | o.Mr = map[string]interface{}{} 84 | o.Mo = map[string]interface{}{} 85 | 86 | expected, _ := json.Marshal(o) 87 | actual, err := Marshal(o) 88 | 89 | assert.NoError(t, err) 90 | assert.Equal( 91 | t, 92 | expected, 93 | actual, 94 | ) 95 | } 96 | 97 | func TestUnmarshalCompat(t *testing.T) { 98 | data := `{ 99 | "sr": "", 100 | "omitempty": 0, 101 | "slr": null, 102 | "mr": {}, 103 | "fr": 0, 104 | "br": false, 105 | "ur": 0, 106 | "str": {}, 107 | "sto": {} 108 | }` 109 | 110 | expected := &Optionals{} 111 | _ = json.Unmarshal([]byte(data), expected) 112 | 113 | actual := &Optionals{} 114 | err := Unmarshal([]byte(data), actual) 115 | 116 | assert.NoError(t, err) 117 | assert.Equal( 118 | t, 119 | expected, 120 | actual, 121 | ) 122 | } 123 | 124 | func TestImplementsPreJSONMarshaler(t *testing.T) { 125 | noHooks := &MixedTypes{} 126 | withHooks := &WithHooks{} 127 | 128 | assert.False(t, ImplementsPreJSONMarshaler(noHooks)) 129 | assert.True(t, ImplementsPreJSONMarshaler(withHooks)) 130 | } 131 | 132 | func TestImplementsPostJSONUnmarshaler(t *testing.T) { 133 | noHooks := &MixedTypes{} 134 | withHooks := &WithHooks{} 135 | 136 | assert.False(t, ImplementsPostJSONUnmarshaler(noHooks)) 137 | assert.True(t, ImplementsPostJSONUnmarshaler(withHooks)) 138 | } 139 | 140 | func TestPreJSONMarshal(t *testing.T) { 141 | noHooks := &MixedTypes{ 142 | I: 1, 143 | B: true, 144 | F: 1.0, 145 | S: "testing", 146 | St: struct { 147 | Foo int `json:"Foo"` 148 | Bar string `json:"Bar"` 149 | }{2, "test"}, 150 | A: []string{"one", "two", "three"}, 151 | } 152 | 153 | withHooks := (*WithHooks)(noHooks) 154 | 155 | expected, _ := json.Marshal(&MixedTypes{ 156 | I: 1 * 1000, 157 | B: !true, 158 | F: 1.0 * 1.1, 159 | S: "TESTING", 160 | St: struct { 161 | Foo int `json:"Foo"` 162 | Bar string `json:"Bar"` 163 | }{2 * 2000, "TEST"}, 164 | A: []string{"ONE", "TWO", "THREE"}, 165 | }) 166 | 167 | gojson, _ := json.Marshal(withHooks) 168 | actualNoHooks, _ := Marshal(noHooks) 169 | actualWithHooks, err := Marshal(withHooks) 170 | 171 | assert.NoError(t, err) 172 | assert.Equal(t, string(gojson), string(actualNoHooks)) 173 | assert.NotEqual(t, string(gojson), string(actualWithHooks)) 174 | assert.NotEqual(t, string(actualNoHooks), string(actualWithHooks)) 175 | assert.Equal(t, string(expected), string(actualWithHooks)) 176 | } 177 | 178 | func TestPostJSONUnmarshal(t *testing.T) { 179 | expected := &WithHooks{ 180 | I: 1, 181 | B: true, 182 | F: 1.0, 183 | S: "testing", 184 | St: struct { 185 | Foo int `json:"Foo"` 186 | Bar string `json:"Bar"` 187 | }{2, "test"}, 188 | A: []string{"one", "two", "three"}, 189 | } 190 | 191 | data := []byte(`{"I":1000,"B":false,"F":1.1,"S":"TESTING","St":{"Foo":4000,"Bar":"TEST"},"A":["ONE","TWO","THREE"]}`) 192 | 193 | gojson := &MixedTypes{} 194 | _ = json.Unmarshal( 195 | data, 196 | gojson, 197 | ) 198 | 199 | withHooks := &WithHooks{} 200 | err := Unmarshal(data, withHooks) 201 | assert.NoError(t, err) 202 | 203 | withoutHooks := &MixedTypes{} 204 | err = Unmarshal(data, withoutHooks) 205 | 206 | assert.NoError(t, err) 207 | assert.NotEqual(t, gojson, withHooks) 208 | assert.NotEqual(t, expected, withoutHooks) 209 | assert.Equal(t, expected, withHooks) 210 | } 211 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= 5 | github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= 6 | github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= 7 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 8 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= 9 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 10 | github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= 11 | github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= 12 | github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= 13 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 14 | github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= 15 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 16 | github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 17 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 18 | github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4= 19 | github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= 20 | github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= 21 | github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= 22 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 23 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 24 | github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= 25 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 26 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= 27 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= 28 | github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= 29 | github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 30 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 31 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 32 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 33 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 34 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 35 | github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= 36 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 37 | github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= 38 | github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= 39 | github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= 40 | github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= 41 | github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= 42 | github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= 43 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 44 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 45 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 46 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= 47 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 48 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 49 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 50 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 51 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 52 | gopkg.in/h2non/gock.v1 v1.0.15 h1:SzLqcIlb/fDfg7UvukMpNcWsu7sI5tWwL+KCATZqks0= 53 | gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE= 54 | gopkg.in/ini.v1 v1.51.1 h1:GyboHr4UqMiLUybYjd22ZjQIKEJEpgtLXtuGbR21Oho= 55 | gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 56 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 57 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 58 | -------------------------------------------------------------------------------- /configdns-v2/errors.go: -------------------------------------------------------------------------------- 1 | package dnsv2 2 | 3 | import ( 4 | "fmt" 5 | client "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 6 | ) 7 | 8 | type ConfigDNSError interface { 9 | error 10 | Network() bool 11 | NotFound() bool 12 | FailedToSave() bool 13 | ValidationFailed() bool 14 | ConcurrencyConflict() bool 15 | } 16 | 17 | func IsConfigDNSError(e error) bool { 18 | _, ok := e.(ConfigDNSError) 19 | return ok 20 | } 21 | 22 | type ZoneError struct { 23 | zoneName string 24 | httpErrorMessage string 25 | apiErrorMessage string 26 | err error 27 | } 28 | 29 | func (e *ZoneError) Network() bool { 30 | if e.httpErrorMessage != "" { 31 | return true 32 | } 33 | return false 34 | } 35 | 36 | func (e *ZoneError) NotFound() bool { 37 | if e.err == nil && e.httpErrorMessage == "" && e.apiErrorMessage == "" { 38 | return true 39 | } else if e.err != nil { 40 | _, ok := e.err.(client.APIError) 41 | if ok && e.err.(client.APIError).Response.StatusCode == 404 { 42 | return true 43 | } 44 | } 45 | return false 46 | } 47 | 48 | func (e *ZoneError) FailedToSave() bool { 49 | return false 50 | } 51 | 52 | func (e *ZoneError) ValidationFailed() bool { 53 | if e.apiErrorMessage != "" { 54 | return true 55 | } 56 | return false 57 | } 58 | 59 | func (e *ZoneError) ConcurrencyConflict() bool { 60 | _, ok := e.err.(client.APIError) 61 | if ok && e.err.(client.APIError).Response.StatusCode == 409 { 62 | return true 63 | } 64 | return false 65 | } 66 | 67 | func (e *ZoneError) Error() string { 68 | if e.Network() { 69 | return fmt.Sprintf("Zone \"%s\" network error: [%s]", e.zoneName, e.httpErrorMessage) 70 | } 71 | 72 | if e.NotFound() { 73 | return fmt.Sprintf("Zone \"%s\" not found.", e.zoneName) 74 | } 75 | 76 | if e.ConcurrencyConflict() { 77 | return fmt.Sprintf("Modification Confict: [%s]", e.apiErrorMessage) 78 | } 79 | 80 | if e.FailedToSave() { 81 | return fmt.Sprintf("Zone \"%s\" failed to save: [%s]", e.zoneName, e.err.Error()) 82 | } 83 | 84 | if e.ValidationFailed() { 85 | return fmt.Sprintf("Zone \"%s\" validation failed: [%s]", e.zoneName, e.apiErrorMessage) 86 | } 87 | 88 | if e.err != nil { 89 | return e.err.Error() 90 | } 91 | 92 | return "" 93 | } 94 | 95 | type RecordError struct { 96 | fieldName string 97 | httpErrorMessage string 98 | apiErrorMessage string 99 | err error 100 | } 101 | 102 | func (e *RecordError) Network() bool { 103 | if e.httpErrorMessage != "" { 104 | return true 105 | } 106 | return false 107 | } 108 | 109 | func (e *RecordError) NotFound() bool { 110 | if e.err == nil && e.httpErrorMessage == "" && e.apiErrorMessage == "" { 111 | return true 112 | } else if e.err != nil { 113 | _, ok := e.err.(client.APIError) 114 | if ok && e.err.(client.APIError).Response.StatusCode == 404 { 115 | return true 116 | } 117 | } 118 | return false 119 | } 120 | 121 | func (e *RecordError) FailedToSave() bool { 122 | if e.fieldName == "" { 123 | return true 124 | } 125 | return false 126 | } 127 | 128 | func (e *RecordError) ValidationFailed() bool { 129 | if e.fieldName != "" && e.err == nil { 130 | return true 131 | } 132 | return false 133 | } 134 | 135 | func (e *RecordError) ConcurrencyConflict() bool { 136 | _, ok := e.err.(client.APIError) 137 | if ok && e.err.(client.APIError).Response.StatusCode == 409 { 138 | return true 139 | } 140 | return false 141 | } 142 | 143 | func (e *RecordError) BadRequest() bool { 144 | _, ok := e.err.(client.APIError) 145 | if ok && e.err.(client.APIError).Status == 400 { 146 | return true 147 | } 148 | return false 149 | } 150 | 151 | func (e *RecordError) Error() string { 152 | if e.Network() { 153 | return fmt.Sprintf("Record network error: [%s]", e.httpErrorMessage) 154 | } 155 | 156 | if e.ConcurrencyConflict() { 157 | return fmt.Sprintf("Modification Confict: [%s]", e.apiErrorMessage) 158 | } 159 | 160 | if e.BadRequest() { 161 | return fmt.Sprintf("Invalid Operation: [%s]", e.apiErrorMessage) 162 | } 163 | 164 | if e.NotFound() { 165 | return fmt.Sprintf("Record not found.") 166 | } 167 | 168 | if e.FailedToSave() { 169 | return fmt.Sprintf("Record failed to save: [%s]", e.err.Error()) 170 | } 171 | 172 | if e.ValidationFailed() { 173 | return fmt.Sprintf("Record validation failed for field [%s]", e.fieldName) 174 | } 175 | 176 | if e.err != nil { 177 | return fmt.Sprintf("%s", e.err.Error()) 178 | } 179 | 180 | return "" 181 | } 182 | 183 | type TsigError struct { 184 | keyName string 185 | httpErrorMessage string 186 | apiErrorMessage string 187 | err error 188 | } 189 | 190 | func (e *TsigError) Network() bool { 191 | if e.httpErrorMessage != "" { 192 | return true 193 | } 194 | return false 195 | } 196 | 197 | func (e *TsigError) NotFound() bool { 198 | if e.err == nil && e.httpErrorMessage == "" && e.apiErrorMessage == "" { 199 | return true 200 | } 201 | return false 202 | } 203 | 204 | func (e *TsigError) FailedToSave() bool { 205 | return false 206 | } 207 | 208 | func (e *TsigError) ValidationFailed() bool { 209 | if e.apiErrorMessage != "" { 210 | return true 211 | } 212 | return false 213 | } 214 | 215 | func (e *TsigError) Error() string { 216 | if e.Network() { 217 | return fmt.Sprintf("Tsig network error: [%s]", e.httpErrorMessage) 218 | } 219 | 220 | if e.NotFound() { 221 | return fmt.Sprintf("tsig key not found.") 222 | } 223 | 224 | if e.FailedToSave() { 225 | return fmt.Sprintf("tsig key failed to save: [%s]", e.err.Error()) 226 | } 227 | 228 | if e.ValidationFailed() { 229 | return fmt.Sprintf("tsig key validation failed: [%s]", e.apiErrorMessage) 230 | } 231 | 232 | return "" 233 | } 234 | -------------------------------------------------------------------------------- /papi-v1/available.go: -------------------------------------------------------------------------------- 1 | package papi 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | 7 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 8 | edge "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 9 | "github.com/xeipuuv/gojsonschema" 10 | ) 11 | 12 | // AvailableCriteria represents a collection of available rule criteria 13 | type AvailableCriteria struct { 14 | client.Resource 15 | ContractID string `json:"contractId"` 16 | GroupID string `json:"groupId"` 17 | ProductID string `json:"productId"` 18 | RuleFormat string `json:"ruleFormat"` 19 | AvailableCriteria struct { 20 | Items []struct { 21 | Name string `json:"name"` 22 | SchemaLink string `json:"schemaLink"` 23 | } `json:"items"` 24 | } `json:"availableCriteria"` 25 | } 26 | 27 | // NewAvailableCriteria creates a new AvailableCriteria 28 | func NewAvailableCriteria() *AvailableCriteria { 29 | availableCriteria := &AvailableCriteria{} 30 | availableCriteria.Init() 31 | 32 | return availableCriteria 33 | } 34 | 35 | // GetAvailableCriteria retrieves criteria available for a given property 36 | // 37 | // API Docs: https://developer.akamai.com/api/luna/papi/resources.html#listavailablecriteria 38 | // Endpoint: GET /papi/v1/properties/{propertyId}/versions/{propertyVersion}/available-criteria{?contractId,groupId} 39 | func (availableCriteria *AvailableCriteria) GetAvailableCriteria(property *Property) error { 40 | req, err := client.NewRequest( 41 | Config, 42 | "GET", 43 | fmt.Sprintf( 44 | "/papi/v1/properties/%s/versions/%d/available-criteria?contractId=%s&groupId=%s", 45 | property.PropertyID, 46 | property.LatestVersion, 47 | property.Contract.ContractID, 48 | property.Group.GroupID, 49 | ), 50 | nil, 51 | ) 52 | if err != nil { 53 | return err 54 | } 55 | 56 | edge.PrintHttpRequest(req, true) 57 | 58 | res, err := client.Do(Config, req) 59 | if err != nil { 60 | return err 61 | } 62 | 63 | edge.PrintHttpResponse(res, true) 64 | 65 | if client.IsError(res) { 66 | return client.NewAPIError(res) 67 | } 68 | 69 | if err = client.BodyJSON(res, availableCriteria); err != nil { 70 | return err 71 | } 72 | 73 | return nil 74 | } 75 | 76 | // AvailableBehaviors represents a collection of available rule behaviors 77 | type AvailableBehaviors struct { 78 | client.Resource 79 | ContractID string `json:"contractId"` 80 | GroupID string `json:"groupId"` 81 | ProductID string `json:"productId"` 82 | RuleFormat string `json:"ruleFormat"` 83 | Behaviors struct { 84 | Items []AvailableBehavior `json:"items"` 85 | } `json:"behaviors"` 86 | } 87 | 88 | // NewAvailableBehaviors creates a new AvailableBehaviors 89 | func NewAvailableBehaviors() *AvailableBehaviors { 90 | availableBehaviors := &AvailableBehaviors{} 91 | availableBehaviors.Init() 92 | 93 | return availableBehaviors 94 | } 95 | 96 | // PostUnmarshalJSON is called after JSON unmarshaling into EdgeHostnames 97 | // 98 | // See: jsonhooks-v1/jsonhooks.Unmarshal() 99 | func (availableBehaviors *AvailableBehaviors) PostUnmarshalJSON() error { 100 | availableBehaviors.Init() 101 | 102 | for key := range availableBehaviors.Behaviors.Items { 103 | availableBehaviors.Behaviors.Items[key].parent = availableBehaviors 104 | } 105 | 106 | availableBehaviors.Complete <- true 107 | 108 | return nil 109 | } 110 | 111 | // GetAvailableBehaviors retrieves available behaviors for a given property 112 | // 113 | // See: Property.GetAvailableBehaviors 114 | // API Docs: https://developer.akamai.com/api/luna/papi/resources.html#listavailablebehaviors 115 | // Endpoint: GET /papi/v1/properties/{propertyId}/versions/{propertyVersion}/available-behaviors{?contractId,groupId} 116 | func (availableBehaviors *AvailableBehaviors) GetAvailableBehaviors(property *Property) error { 117 | req, err := client.NewRequest( 118 | Config, 119 | "GET", 120 | fmt.Sprintf( 121 | "/papi/v1/properties/%s/versions/%d/available-behaviors?contractId=%s&groupId=%s", 122 | property.PropertyID, 123 | property.LatestVersion, 124 | property.Contract.ContractID, 125 | property.Group.GroupID, 126 | ), 127 | nil, 128 | ) 129 | if err != nil { 130 | return err 131 | } 132 | 133 | edge.PrintHttpRequest(req, true) 134 | 135 | res, err := client.Do(Config, req) 136 | if err != nil { 137 | return err 138 | } 139 | 140 | edge.PrintHttpResponse(res, true) 141 | 142 | if client.IsError(res) { 143 | return client.NewAPIError(res) 144 | } 145 | 146 | if err = client.BodyJSON(res, availableBehaviors); err != nil { 147 | return err 148 | } 149 | 150 | return nil 151 | } 152 | 153 | // AvailableBehavior represents an available behavior resource 154 | type AvailableBehavior struct { 155 | client.Resource 156 | parent *AvailableBehaviors 157 | Name string `json:"name"` 158 | SchemaLink string `json:"schemaLink"` 159 | } 160 | 161 | // NewAvailableBehavior creates a new AvailableBehavior 162 | func NewAvailableBehavior(parent *AvailableBehaviors) *AvailableBehavior { 163 | availableBehavior := &AvailableBehavior{parent: parent} 164 | availableBehavior.Init() 165 | 166 | return availableBehavior 167 | } 168 | 169 | // GetSchema retrieves the JSON schema for an available behavior 170 | func (behavior *AvailableBehavior) GetSchema() (*gojsonschema.Schema, error) { 171 | req, err := client.NewRequest( 172 | Config, 173 | "GET", 174 | behavior.SchemaLink, 175 | nil, 176 | ) 177 | if err != nil { 178 | return nil, err 179 | } 180 | 181 | res, err := client.Do(Config, req) 182 | if err != nil { 183 | return nil, err 184 | } 185 | 186 | schemaBytes, _ := ioutil.ReadAll(res.Body) 187 | schemaBody := string(schemaBytes) 188 | loader := gojsonschema.NewStringLoader(schemaBody) 189 | schema, err := gojsonschema.NewSchema(loader) 190 | 191 | return schema, err 192 | } 193 | -------------------------------------------------------------------------------- /configdns-v2/recordsets.go: -------------------------------------------------------------------------------- 1 | package dnsv2 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 7 | edge "github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid" 8 | "strconv" 9 | "sync" 10 | ) 11 | 12 | var ( 13 | zoneRecordsetsWriteLock sync.Mutex 14 | ) 15 | 16 | // Recordset Query args struct 17 | type RecordsetQueryArgs struct { 18 | Page int 19 | PageSize int 20 | Search string 21 | ShowAll bool 22 | SortBy string 23 | Types string 24 | } 25 | 26 | // Recordsets Struct. Used for Create and Update Recordsets 27 | type Recordsets struct { 28 | Recordsets []Recordset `json:"recordsets"` 29 | } 30 | 31 | type Recordset struct { 32 | Name string `json:"name"` 33 | Type string `json:"type"` 34 | TTL int `json:"ttl"` 35 | Rdata []string `json:"rdata"` 36 | } //`json:"recordsets"` 37 | 38 | type MetadataH struct { 39 | LastPage int `json:"lastPage"` 40 | Page int `json:"page"` 41 | PageSize int `json:"pageSize"` 42 | ShowAll bool `json:"showAll"` 43 | TotalElements int `json:"totalElements"` 44 | } //`json:"metadata"` 45 | 46 | type RecordSetResponse struct { 47 | Metadata MetadataH `json:"metadata"` 48 | Recordsets []Recordset `json:"recordsets"` 49 | } 50 | 51 | func NewRecordSetResponse(name string) *RecordSetResponse { 52 | recordset := &RecordSetResponse{} 53 | return recordset 54 | } 55 | 56 | // Get RecordSets with Query Args. No formatting of arg values! 57 | func GetRecordsets(zone string, queryArgs ...RecordsetQueryArgs) (*RecordSetResponse, error) { 58 | 59 | recordsetResp := NewRecordSetResponse("") 60 | 61 | // construct GET url 62 | getURL := fmt.Sprintf("/config-dns/v2/zones/%s/recordsets", zone) 63 | if len(queryArgs) > 1 { 64 | return nil, errors.New("GetRecordsets QueryArgs invalid.") 65 | } 66 | 67 | req, err := client.NewRequest( 68 | Config, 69 | "GET", 70 | getURL, 71 | nil, 72 | ) 73 | if err != nil { 74 | return nil, err 75 | } 76 | 77 | q := req.URL.Query() 78 | if len(queryArgs) > 0 { 79 | if queryArgs[0].Page > 0 { 80 | q.Add("page", strconv.Itoa(queryArgs[0].Page)) 81 | } 82 | if queryArgs[0].PageSize > 0 { 83 | q.Add("pageSize", strconv.Itoa(queryArgs[0].PageSize)) 84 | } 85 | if queryArgs[0].Search != "" { 86 | q.Add("search", queryArgs[0].Search) 87 | } 88 | q.Add("showAll", strconv.FormatBool(queryArgs[0].ShowAll)) 89 | if queryArgs[0].SortBy != "" { 90 | q.Add("sortBy", queryArgs[0].SortBy) 91 | } 92 | if queryArgs[0].Types != "" { 93 | q.Add("types", queryArgs[0].Types) 94 | } 95 | req.URL.RawQuery = q.Encode() 96 | } 97 | 98 | edge.PrintHttpRequest(req, true) 99 | 100 | res, err := client.Do(Config, req) 101 | if err != nil { 102 | return nil, err 103 | } 104 | 105 | edge.PrintHttpResponse(res, true) 106 | 107 | if client.IsError(res) && res.StatusCode != 404 { 108 | return nil, client.NewAPIError(res) 109 | } else if res.StatusCode == 404 { 110 | return nil, &ZoneError{zoneName: zone} 111 | } else { 112 | err = client.BodyJSON(res, recordsetResp) 113 | if err != nil { 114 | return nil, err 115 | } 116 | return recordsetResp, nil 117 | } 118 | } 119 | 120 | // Create Recordstes 121 | func (recordsets *Recordsets) Save(zone string, recLock ...bool) error { 122 | // This lock will restrict the concurrency of API calls 123 | // to 1 save request at a time. This is needed for the Soa.Serial value which 124 | // is required to be incremented for every subsequent update to a zone 125 | // so we have to save just one request at a time to ensure this is always 126 | // incremented properly 127 | 128 | if localLock(recLock) { 129 | zoneRecordsetsWriteLock.Lock() 130 | defer zoneRecordsetsWriteLock.Unlock() 131 | } 132 | 133 | req, err := client.NewJSONRequest( 134 | Config, 135 | "POST", 136 | "/config-dns/v2/zones/"+zone+"/recordsets", 137 | recordsets, 138 | ) 139 | if err != nil { 140 | return err 141 | } 142 | 143 | edge.PrintHttpRequest(req, true) 144 | 145 | res, err := client.Do(Config, req) 146 | 147 | // Network error 148 | if err != nil { 149 | return &ZoneError{ 150 | zoneName: zone, 151 | httpErrorMessage: err.Error(), 152 | err: err, 153 | } 154 | } 155 | 156 | edge.PrintHttpResponse(res, true) 157 | 158 | // API error 159 | if client.IsError(res) { 160 | err := client.NewAPIError(res) 161 | return &ZoneError{zoneName: zone, apiErrorMessage: err.Detail, err: err} 162 | } 163 | 164 | return nil 165 | } 166 | 167 | func (recordsets *Recordsets) Update(zone string, recLock ...bool) error { 168 | // This lock will restrict the concurrency of API calls 169 | // to 1 save request at a time. This is needed for the Soa.Serial value which 170 | // is required to be incremented for every subsequent update to a zone 171 | // so we have to save just one request at a time to ensure this is always 172 | // incremented properly 173 | 174 | if localLock(recLock) { 175 | zoneRecordsetsWriteLock.Lock() 176 | defer zoneRecordsetsWriteLock.Unlock() 177 | } 178 | 179 | req, err := client.NewJSONRequest( 180 | Config, 181 | "PUT", 182 | "/config-dns/v2/zones/"+zone+"/recordsets", 183 | recordsets, 184 | ) 185 | if err != nil { 186 | return err 187 | } 188 | 189 | edge.PrintHttpRequest(req, true) 190 | 191 | res, err := client.Do(Config, req) 192 | 193 | // Network error 194 | if err != nil { 195 | return &ZoneError{ 196 | zoneName: zone, 197 | httpErrorMessage: err.Error(), 198 | err: err, 199 | } 200 | } 201 | 202 | edge.PrintHttpResponse(res, true) 203 | 204 | // API error 205 | if client.IsError(res) { 206 | err := client.NewAPIError(res) 207 | return &ZoneError{zoneName: zone, apiErrorMessage: err.Detail, err: err} 208 | } 209 | 210 | return nil 211 | } 212 | -------------------------------------------------------------------------------- /cps-v2/enrollments.go: -------------------------------------------------------------------------------- 1 | package cps 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "time" 7 | 8 | client "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 9 | ) 10 | 11 | // Enrollments represents an enrollment 12 | // 13 | // API Docs: https://developer.akamai.com/api/core_features/certificate_provisioning_system/v2.html#enrollments 14 | type Enrollment struct { 15 | client.Resource 16 | AdminContact *Contact `json:"adminContact"` 17 | CertificateChainType *string `json:"certificateChainType"` 18 | CertificateType CertificateType `json:"certificateType"` 19 | CertificateSigningRequest *CSR `json:"csr"` 20 | ChangeManagement bool `json:"changeManagement"` 21 | EnableMultiStacked bool `json:"enableMultiStackedCertificates"` 22 | Location *string `json:"location"` 23 | MaxAllowedSans *int `json:"maxAllowedSanNames"` 24 | MaxAllowedWildcardSans *int `json:"maxAllowedWildcardSanNames"` 25 | NetworkConfiguration *NetworkConfiguration `json:"networkConfiguration"` 26 | Organization *Organization `json:"org"` 27 | PendingChanges *[]string `json:"pendingChanges"` 28 | RegistrationAuthority RegistrationAuthority `json:"ra"` 29 | SignatureAuthority *SHA `json:"signatureAlgorithm"` 30 | TechContact *Contact `json:"techContact"` 31 | ThirdParty *ThirdParty `json:"thirdParty"` 32 | ValidationType ValidationType `json:"validationType"` 33 | } 34 | 35 | type CreateEnrollmentQueryParams struct { 36 | ContractID string 37 | DeployNotAfter *string 38 | DeployNotBefore *string 39 | } 40 | 41 | type ListEnrollmentsQueryParams struct { 42 | ContractID string 43 | } 44 | 45 | type CreateEnrollmentResponse struct { 46 | Location string `json:"enrollment"` 47 | Changes []string `json:"changes"` 48 | } 49 | 50 | func formatTime(t time.Time) string { 51 | return fmt.Sprintf("%d-%02d-%02d", t.Year(), t.Month(), t.Day()) 52 | } 53 | 54 | // Create an Enrollment on CPS 55 | // 56 | // 57 | // API Docs: https://developer.akamai.com/api/core_features/certificate_provisioning_system/v2.html#5aaa335c 58 | // Endpoint: POST /cps/v2/enrollments{?contractId,deploy-not-after,deploy-not-before} 59 | func (enrollment *Enrollment) Create(params CreateEnrollmentQueryParams) (*CreateEnrollmentResponse, error) { 60 | var request = fmt.Sprintf( 61 | "/cps/v2/enrollments?contractId=%s", 62 | params.ContractID, 63 | ) 64 | 65 | if params.DeployNotAfter != nil { 66 | request = fmt.Sprintf( 67 | "%s&deploy-not-after=%s", 68 | request, 69 | *params.DeployNotAfter, 70 | ) 71 | } 72 | 73 | if params.DeployNotBefore != nil { 74 | request = fmt.Sprintf( 75 | "%s&deploy-not-before=%s", 76 | request, 77 | *params.DeployNotBefore, 78 | ) 79 | } 80 | 81 | req, err := newRequest( 82 | "POST", 83 | request, 84 | enrollment, 85 | ) 86 | 87 | if err != nil { 88 | return nil, err 89 | } 90 | 91 | res, err := client.Do(Config, req) 92 | 93 | if err != nil { 94 | return nil, err 95 | } 96 | 97 | if client.IsError(res) { 98 | return nil, client.NewAPIError(res) 99 | } 100 | 101 | var response CreateEnrollmentResponse 102 | if err = client.BodyJSON(res, &response); err != nil { 103 | return nil, err 104 | } 105 | 106 | return &response, nil 107 | } 108 | 109 | // Get an enrollment by location 110 | // 111 | // 112 | // API Docs: https://developer.akamai.com/api/core_features/certificate_provisioning_system/v2.html#getasingleenrollment 113 | // Endpoint: POST /cps/v2/enrollments/{enrollmentId} 114 | func GetEnrollment(location string) (*Enrollment, error) { 115 | req, err := client.NewRequest( 116 | Config, 117 | "GET", 118 | location, 119 | nil, 120 | ) 121 | 122 | if err != nil { 123 | return nil, err 124 | } 125 | 126 | req.Header.Add("Accept", "application/vnd.akamai.cps.enrollment.v7+json") 127 | 128 | res, err := client.Do(Config, req) 129 | 130 | if err != nil { 131 | return nil, err 132 | } 133 | 134 | if client.IsError(res) { 135 | return nil, client.NewAPIError(res) 136 | } 137 | 138 | var response Enrollment 139 | if err = client.BodyJSON(res, &response); err != nil { 140 | return nil, err 141 | } 142 | 143 | return &response, nil 144 | } 145 | 146 | func ListEnrollments(params ListEnrollmentsQueryParams) ([]Enrollment, error) { 147 | var enrollments []Enrollment 148 | 149 | req, err := client.NewRequest( 150 | Config, 151 | "GET", 152 | fmt.Sprintf( 153 | "/cps/v2/enrollments?contractId={%s}", 154 | params.ContractID, 155 | ), 156 | nil, 157 | ) 158 | if err != nil { 159 | return nil, err 160 | } 161 | 162 | res, err := client.Do(Config, req) 163 | if err != nil { 164 | return nil, err 165 | } 166 | 167 | if client.IsError(res) { 168 | return nil, client.NewAPIError(res) 169 | } 170 | 171 | if err = client.BodyJSON(res, enrollments); err != nil { 172 | return nil, err 173 | } 174 | 175 | return enrollments, nil 176 | } 177 | 178 | func (enrollment *Enrollment) Exists(enrollments []Enrollment) bool { 179 | for _, e := range enrollments { 180 | if e.CertificateSigningRequest.CommonName == enrollment.CertificateSigningRequest.CommonName { 181 | return true 182 | } 183 | } 184 | 185 | return false 186 | } 187 | 188 | // CreateEnrollment wraps enrollment.Create to accept json 189 | func CreateEnrollment(data []byte, params CreateEnrollmentQueryParams) (*CreateEnrollmentResponse, error) { 190 | var enrollment Enrollment 191 | if err := json.Unmarshal(data, &enrollment); err != nil { 192 | return nil, err 193 | } 194 | 195 | return enrollment.Create(params) 196 | } 197 | -------------------------------------------------------------------------------- /reportsgtm-v1/property.go: -------------------------------------------------------------------------------- 1 | package reportsgtm 2 | 3 | import ( 4 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 5 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/configgtm-v1_3" 6 | 7 | "fmt" 8 | ) 9 | 10 | // 11 | // Support gtm reports thru Edgegrid 12 | // Based on 1.0 Schema 13 | // 14 | 15 | // Property Traffic Report Structs 16 | type PropertyTMeta struct { 17 | Uri string `json:uri"` 18 | Domain string `json:"domain"` 19 | Interval string `json:"interval,omitempty"` 20 | Property string `json:"property"` 21 | Start string `json:"start"` 22 | End string `json:"end"` 23 | } 24 | 25 | type PropertyDRow struct { 26 | Nickname string `json:"nickname"` 27 | DatacenterId int `json:"datacenterId"` 28 | TrafficTargetName string `json:"trafficTargetName"` 29 | Requests int64 `json:"requests"` 30 | Status string `json:"status"` 31 | } 32 | 33 | type PropertyTData struct { 34 | Timestamp string `json:"timestamp"` 35 | Datacenters []*PropertyDRow `json:"datacenters"` 36 | } 37 | 38 | // The Property Traffic Response structure returned by the Reports API 39 | type PropertyTrafficResponse struct { 40 | Metadata *PropertyTMeta `json:"metadata"` 41 | DataRows []*PropertyTData `json:"dataRows"` 42 | DataSummary interface{} `json:"dataSummary"` 43 | Links []*configgtm.Link `json:"links"` 44 | } 45 | 46 | // 47 | // IP Status By Property Structs 48 | // 49 | 50 | // IP Availability Status Response structure returned by the Reports API. 51 | type IPStatusPerProperty struct { 52 | Metadata *IpStatPerPropMeta `json:"metadata"` 53 | DataRows []*IpStatPerPropData `json:"dataRows"` 54 | DataSummary interface{} `json:"dataSummary"` 55 | Links []*configgtm.Link `json:"links"` 56 | } 57 | 58 | type IpStatPerPropMeta struct { 59 | Uri string `json:uri"` 60 | Domain string `json:"domain"` 61 | Property string `json:"property"` 62 | Start string `json:"start"` 63 | End string `json:"end"` 64 | MostRecent bool `json:"mostRecent"` 65 | Ip string `json:"ip"` 66 | DatacenterId int `json:"datacenterId"` 67 | } 68 | 69 | type IpStatPerPropData struct { 70 | Timestamp string `json:"timestamp"` 71 | CutOff float64 `json:"cutOff"` 72 | Datacenters []*IpStatPerPropDRow `json:"datacenters"` 73 | } 74 | 75 | type IpStatPerPropDRow struct { 76 | Nickname string `json:"nickname"` 77 | DatacenterId int `json:"datacenterId"` 78 | TrafficTargetName string `json:"trafficTargetName"` 79 | IPs []*IpStatIp `json:"IPs"` 80 | } 81 | 82 | type IpStatIp struct { 83 | Ip string `json:"ip"` 84 | HandedOut bool `json:"handedOut"` 85 | Score float32 `json:"score"` 86 | Alive bool `json:"alive"` 87 | } 88 | 89 | // GetIpStatusPerProperty retrieves current IP Availability Status for specified property in the given domainname. 90 | func GetIpStatusPerProperty(domainName string, propertyName string, optArgs map[string]string) (*IPStatusPerProperty, error) { 91 | stat := &IPStatusPerProperty{} 92 | hostURL := fmt.Sprintf("/gtm-api/v1/reports/ip-availability/domains/%s/properties/%s", domainName, propertyName) 93 | 94 | req, err := client.NewRequest( 95 | Config, 96 | "GET", 97 | hostURL, 98 | nil, 99 | ) 100 | if err != nil { 101 | return nil, err 102 | } 103 | 104 | // Look for and process optional query params 105 | q := req.URL.Query() 106 | for k, v := range optArgs { 107 | switch k { 108 | case "start": 109 | fallthrough 110 | case "end": 111 | fallthrough 112 | case "ip": 113 | fallthrough 114 | case "mostRecent": 115 | fallthrough 116 | case "datacenterId": 117 | q.Add(k, v) 118 | } 119 | } 120 | if optArgs != nil { 121 | req.URL.RawQuery = q.Encode() 122 | } 123 | 124 | // time stamps require urlencoded content header 125 | setEncodedHeader(req) 126 | 127 | // print/log the request if warranted 128 | printHttpRequest(req, true) 129 | 130 | res, err := client.Do(Config, req) 131 | if err != nil { 132 | return nil, err 133 | } 134 | 135 | // print/log the response if warranted 136 | printHttpResponse(res, true) 137 | 138 | if client.IsError(res) && res.StatusCode != 404 { 139 | return nil, client.NewAPIError(res) 140 | } else if res.StatusCode == 404 { 141 | cErr := configgtm.CommonError{} 142 | cErr.SetItem("entityName", "Property") 143 | cErr.SetItem("name", propertyName) 144 | return nil, cErr 145 | } else { 146 | err = client.BodyJSON(res, stat) 147 | if err != nil { 148 | return nil, err 149 | } 150 | 151 | return stat, nil 152 | } 153 | } 154 | 155 | // GetTrafficPerProperty retrieves report traffic for the specified property in the specified domain. 156 | func GetTrafficPerProperty(domainName string, propertyName string, optArgs map[string]string) (*PropertyTrafficResponse, error) { 157 | stat := &PropertyTrafficResponse{} 158 | hostURL := fmt.Sprintf("/gtm-api/v1/reports/traffic/domains/%s/properties/%s", domainName, propertyName) 159 | 160 | req, err := client.NewRequest( 161 | Config, 162 | "GET", 163 | hostURL, 164 | nil, 165 | ) 166 | if err != nil { 167 | return nil, err 168 | } 169 | 170 | // Look for and process optional query params 171 | q := req.URL.Query() 172 | for k, v := range optArgs { 173 | switch k { 174 | case "start": 175 | fallthrough 176 | case "end": 177 | q.Add(k, v) 178 | } 179 | } 180 | if optArgs != nil { 181 | req.URL.RawQuery = q.Encode() 182 | } 183 | 184 | // time stamps require urlencoded content header 185 | setEncodedHeader(req) 186 | 187 | // print/log the request if warranted 188 | printHttpRequest(req, true) 189 | 190 | res, err := client.Do(Config, req) 191 | if err != nil { 192 | return nil, err 193 | } 194 | 195 | // print/log the response if warranted 196 | printHttpResponse(res, true) 197 | 198 | if client.IsError(res) && res.StatusCode != 404 { 199 | return nil, client.NewAPIError(res) 200 | } else if res.StatusCode == 404 { 201 | cErr := configgtm.CommonError{} 202 | cErr.SetItem("entityName", "Property") 203 | cErr.SetItem("name", propertyName) 204 | return nil, cErr 205 | } else { 206 | err = client.BodyJSON(res, stat) 207 | if err != nil { 208 | return nil, err 209 | } 210 | 211 | return stat, nil 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /apikey-manager-v1/collections.go: -------------------------------------------------------------------------------- 1 | package apikeymanager 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1" 7 | ) 8 | 9 | type Collections []Collection 10 | 11 | type Collection struct { 12 | Id int `json:"id,omitempty"` 13 | Name string `json:"name,omitempty"` 14 | Description string `json:"description,omitempty"` 15 | KeyCount int `json:"keyCount,omitempty"` 16 | Dirty bool `json:"dirty,omitempty"` 17 | ContractId string `json:"contractId,omitempty"` 18 | GroupId int `json:"groupId,omitempty"` 19 | GrantedACL []string `json:"grantedACL,omitempty"` 20 | DirtyACL []string `json:"dirtyACL,omitempty"` 21 | Quota Quota `json:"quota,omitempty"` 22 | } 23 | 24 | func ListCollections() (*Collections, error) { 25 | req, err := client.NewJSONRequest( 26 | Config, 27 | "GET", 28 | "/apikey-manager-api/v1/collections", 29 | nil, 30 | ) 31 | 32 | if err != nil { 33 | return nil, err 34 | } 35 | 36 | res, err := client.Do(Config, req) 37 | 38 | if err != nil { 39 | return nil, err 40 | } 41 | 42 | if client.IsError(res) { 43 | return nil, client.NewAPIError(res) 44 | } 45 | 46 | rep := &Collections{} 47 | if err = client.BodyJSON(res, rep); err != nil { 48 | return nil, err 49 | } 50 | 51 | return rep, nil 52 | } 53 | 54 | type CreateCollectionOptions struct { 55 | ContractId string `json:"contractId,omitempty"` 56 | GroupId int `json:"groupId,omitempty"` 57 | Name string `json:"name,omitempty"` 58 | Description string `json:"description,omitempty"` 59 | } 60 | 61 | func CreateCollection(options *CreateCollectionOptions) (*Collection, error) { 62 | req, err := client.NewJSONRequest( 63 | Config, 64 | "POST", 65 | "/apikey-manager-api/v1/collections", 66 | options, 67 | ) 68 | 69 | if err != nil { 70 | return nil, err 71 | } 72 | 73 | res, err := client.Do(Config, req) 74 | 75 | if err != nil { 76 | return nil, err 77 | } 78 | 79 | if client.IsError(res) { 80 | return nil, client.NewAPIError(res) 81 | } 82 | 83 | rep := &Collection{} 84 | if err = client.BodyJSON(res, rep); err != nil { 85 | return nil, err 86 | } 87 | 88 | return rep, nil 89 | } 90 | 91 | func GetCollection(collectionId int) (*Collection, error) { 92 | req, err := client.NewJSONRequest( 93 | Config, 94 | "GET", 95 | fmt.Sprintf("/apikey-manager-api/v1/collections/%d", collectionId), 96 | nil, 97 | ) 98 | 99 | if err != nil { 100 | return nil, err 101 | } 102 | 103 | res, err := client.Do(Config, req) 104 | 105 | if err != nil { 106 | return nil, err 107 | } 108 | 109 | if client.IsError(res) { 110 | return nil, client.NewAPIError(res) 111 | } 112 | 113 | rep := &Collection{} 114 | if err = client.BodyJSON(res, rep); err != nil { 115 | return nil, err 116 | } 117 | 118 | return rep, nil 119 | } 120 | 121 | func CollectionAclAllow(collectionId int, acl []string) (*Collection, error) { 122 | collection, err := GetCollection(collectionId) 123 | if err != nil { 124 | return collection, err 125 | } 126 | 127 | acl = append(acl, collection.GrantedACL...) 128 | 129 | req, err := client.NewJSONRequest( 130 | Config, 131 | "PUT", 132 | fmt.Sprintf("/apikey-manager-api/v1/collections/%d/acl", collectionId), 133 | acl, 134 | ) 135 | 136 | if err != nil { 137 | return nil, err 138 | } 139 | 140 | res, err := client.Do(Config, req) 141 | 142 | if err != nil { 143 | return nil, err 144 | } 145 | 146 | if client.IsError(res) { 147 | return nil, client.NewAPIError(res) 148 | } 149 | 150 | rep := &Collection{} 151 | if err = client.BodyJSON(res, rep); err != nil { 152 | return nil, err 153 | } 154 | 155 | return rep, nil 156 | } 157 | 158 | func CollectionAclDeny(collectionId int, acl []string) (*Collection, error) { 159 | collection, err := GetCollection(collectionId) 160 | if err != nil { 161 | return collection, err 162 | } 163 | 164 | for cIndex, currentAcl := range collection.GrantedACL { 165 | for _, newAcl := range acl { 166 | if newAcl == currentAcl { 167 | collection.GrantedACL = append( 168 | collection.GrantedACL[:cIndex], 169 | collection.GrantedACL[cIndex+1:]..., 170 | ) 171 | } 172 | } 173 | } 174 | 175 | req, err := client.NewJSONRequest( 176 | Config, 177 | "PUT", 178 | fmt.Sprintf("/apikey-manager-api/v1/collections/%d/acl", collectionId), 179 | collection.GrantedACL, 180 | ) 181 | 182 | if err != nil { 183 | return nil, err 184 | } 185 | 186 | res, err := client.Do(Config, req) 187 | 188 | if err != nil { 189 | return nil, err 190 | } 191 | 192 | if client.IsError(res) { 193 | return nil, client.NewAPIError(res) 194 | } 195 | 196 | rep := &Collection{} 197 | if err = client.BodyJSON(res, rep); err != nil { 198 | return nil, err 199 | } 200 | 201 | return rep, nil 202 | } 203 | 204 | type Quota struct { 205 | Enabled bool `json:"enabled,omitempty"` 206 | Value int `json:"value,omitempty"` 207 | Interval string `json:"interval,omitempty"` 208 | Headers struct { 209 | DenyLimitHeaderShown bool `json:"denyLimitHeaderShown,omitempty"` 210 | DenyRemainingHeaderShown bool `json:"denyRemainingHeaderShown,omitempty"` 211 | DenyNextHeaderShown bool `json:"denyNextHeaderShown,omitempty"` 212 | AllowLimitHeaderShown bool `json:"allowLimitHeaderShown,omitempty"` 213 | AllowRemainingHeaderShown bool `json:"allowRemainingHeaderShown,omitempty"` 214 | AllowResetHeaderShown bool `json:"allowResetHeaderShown,omitempty"` 215 | } `json:"headers,omitempty"` 216 | } 217 | 218 | func CollectionSetQuota(collectionId int, value int) (*Collection, error) { 219 | collection, err := GetCollection(collectionId) 220 | if err != nil { 221 | return collection, err 222 | } 223 | 224 | collection.Quota.Value = value 225 | req, err := client.NewJSONRequest( 226 | Config, 227 | "PUT", 228 | fmt.Sprintf("/apikey-manager-api/v1/collections/%d/quota", collectionId), 229 | collection.Quota, 230 | ) 231 | 232 | if err != nil { 233 | return nil, err 234 | } 235 | 236 | res, err := client.Do(Config, req) 237 | 238 | if err != nil { 239 | return nil, err 240 | } 241 | 242 | if client.IsError(res) { 243 | return nil, client.NewAPIError(res) 244 | } 245 | 246 | rep := &Collection{} 247 | if err = client.BodyJSON(res, rep); err != nil { 248 | return nil, err 249 | } 250 | 251 | return rep, nil 252 | } 253 | --------------------------------------------------------------------------------